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
Boxiang Sun
cython
Commits
e2d55c56
Commit
e2d55c56
authored
Sep 22, 2018
by
Stefan Behnel
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'master' into release
parents
c10046b9
4308e1e7
Changes
20
Hide whitespace changes
Inline
Side-by-side
Showing
20 changed files
with
335 additions
and
86 deletions
+335
-86
.editorconfig
.editorconfig
+23
-0
CHANGES.rst
CHANGES.rst
+13
-0
Cython/Compiler/ExprNodes.py
Cython/Compiler/ExprNodes.py
+23
-5
Cython/Compiler/ModuleNode.py
Cython/Compiler/ModuleNode.py
+1
-1
Cython/Compiler/Nodes.py
Cython/Compiler/Nodes.py
+9
-3
Cython/Compiler/Options.py
Cython/Compiler/Options.py
+9
-8
Cython/Compiler/ParseTreeTransforms.py
Cython/Compiler/ParseTreeTransforms.py
+54
-45
Cython/Compiler/Visitor.pxd
Cython/Compiler/Visitor.pxd
+2
-1
Cython/Compiler/Visitor.py
Cython/Compiler/Visitor.py
+7
-1
Cython/Includes/libc/math.pxd
Cython/Includes/libc/math.pxd
+20
-20
Cython/Shadow.py
Cython/Shadow.py
+1
-1
Cython/Utility/TypeConversion.c
Cython/Utility/TypeConversion.c
+1
-1
tests/memoryview/memoryview_annotation_typing.py
tests/memoryview/memoryview_annotation_typing.py
+18
-0
tests/run/async_globals.pyx
tests/run/async_globals.pyx
+20
-0
tests/run/cpp_exceptions.pyx
tests/run/cpp_exceptions.pyx
+15
-0
tests/run/cpp_exceptions_helper.h
tests/run/cpp_exceptions_helper.h
+9
-0
tests/run/exttype_freelist.pyx
tests/run/exttype_freelist.pyx
+16
-0
tests/run/import_star.pyx
tests/run/import_star.pyx
+12
-0
tests/run/pure_parallel.py
tests/run/pure_parallel.py
+60
-0
tests/run/purecdef.py
tests/run/purecdef.py
+22
-0
No files found.
.editorconfig
0 → 100644
View file @
e2d55c56
# top-most EditorConfig file
root = true
# Unix-style newlines with a newline ending every file
[*]
end_of_line = lf
insert_final_newline = true
max_line_length = 120
# 4 space indentation
[*.{py,pyx,pxi,pxd,c,cpp,h,hpp}]
indent_style = space
indent_size = 4
trim_trailing_whitespace = true
# Tab indentation (no size specified)
[Makefile]
indent_style = tab
# Matches the exact files either package.json or .travis.yml
[{package.json,.travis.yml}]
indent_style = space
indent_size = 2
CHANGES.rst
View file @
e2d55c56
...
...
@@ -71,6 +71,8 @@ Features added
* New C macro ``CYTHON_HEX_VERSION`` to access Cython'
s
version
in
the
same
style
as
``
PY_HEX_VERSION
``.
*
Constants
in
``
libc
.
math
``
are
now
declared
as
``
const
``
to
simplify
their
handling
.
Bugs
fixed
----------
...
...
@@ -102,6 +104,13 @@ Bugs fixed
* Fix declarations of builtin or C types using strings in pure python mode.
(Github issue #2046)
* Generator expressions and lambdas failed to compile in ``@cfunc`` functions.
(Github issue #459)
* Global names with ``const`` types were not excluded from star-import assignments
which could lead to invalid C code.
(Github issue #2621)
* Several internal function signatures were fixed that lead to warnings in gcc-8.
(Github issue #2363)
...
...
@@ -123,6 +132,10 @@ Bugs fixed
module state. It now raises an exception instead, given that reloading is
not actually supported.
* Object-returning, C++ exception throwing functions were not checking that
the return value was non-null.
Original patch by Matt Wozniski (Github Issue #2603)
Other changes
-------------
...
...
Cython/Compiler/ExprNodes.py
View file @
e2d55c56
...
...
@@ -197,10 +197,12 @@ def get_exception_handler(exception_value):
else
:
return
'%s(); if (!PyErr_Occurred()) PyErr_SetString(PyExc_RuntimeError , "Error converting c++ exception.");'
%
exception_value
.
entry
.
cname
def
translate_cpp_exception
(
code
,
pos
,
inside
,
exception_value
,
nogil
):
def
translate_cpp_exception
(
code
,
pos
,
inside
,
py_result
,
exception_value
,
nogil
):
raise_py_exception
=
get_exception_handler
(
exception_value
)
code
.
putln
(
"try {"
)
code
.
putln
(
"%s"
%
inside
)
if
py_result
:
code
.
putln
(
code
.
error_goto_if_null
(
py_result
,
pos
))
code
.
putln
(
"} catch(...) {"
)
if
nogil
:
code
.
put_ensure_gil
(
declare_gilstate
=
True
)
...
...
@@ -2306,7 +2308,11 @@ class NameNode(AtomicExprNode):
if
overloaded_assignment
:
result
=
rhs
.
result
()
if
exception_check
==
'+'
:
translate_cpp_exception
(
code
,
self
.
pos
,
'%s = %s;'
%
(
self
.
result
(),
result
),
exception_value
,
self
.
in_nogil_context
)
translate_cpp_exception
(
code
,
self
.
pos
,
'%s = %s;'
%
(
self
.
result
(),
result
),
self
.
result
()
if
self
.
type
.
is_pyobject
else
None
,
exception_value
,
self
.
in_nogil_context
)
else
:
code
.
putln
(
'%s = %s;'
%
(
self
.
result
(),
result
))
else
:
...
...
@@ -3978,6 +3984,7 @@ class IndexNode(_IndexingBaseNode):
translate_cpp_exception
(
code
,
self
.
pos
,
"%s = %s[%s];"
%
(
self
.
result
(),
self
.
base
.
result
(),
self
.
index
.
result
()),
self
.
result
()
if
self
.
type
.
is_pyobject
else
None
,
self
.
exception_value
,
self
.
in_nogil_context
)
else
:
error_check
=
'!%s'
if
error_value
==
'NULL'
else
'%%s == %s'
%
error_value
...
...
@@ -4048,6 +4055,7 @@ class IndexNode(_IndexingBaseNode):
# both exception handlers are the same.
translate_cpp_exception
(
code
,
self
.
pos
,
"%s = %s;"
%
(
self
.
result
(),
rhs
.
result
()),
self
.
result
()
if
self
.
lhs
.
is_pyobject
else
None
,
self
.
exception_value
,
self
.
in_nogil_context
)
else
:
code
.
putln
(
...
...
@@ -5838,7 +5846,7 @@ class SimpleCallNode(CallNode):
elif
self
.
type
.
is_memoryviewslice
:
assert
self
.
is_temp
exc_checks
.
append
(
self
.
type
.
error_condition
(
self
.
result
()))
el
se
:
el
if
func_type
.
exception_check
!=
'+'
:
exc_val
=
func_type
.
exception_value
exc_check
=
func_type
.
exception_check
if
exc_val
is
not
None
:
...
...
@@ -5861,6 +5869,7 @@ class SimpleCallNode(CallNode):
lhs
=
""
if
func_type
.
exception_check
==
'+'
:
translate_cpp_exception
(
code
,
self
.
pos
,
'%s%s;'
%
(
lhs
,
rhs
),
self
.
result
()
if
self
.
type
.
is_pyobject
else
None
,
func_type
.
exception_value
,
self
.
nogil
)
else
:
if
(
self
.
overflowcheck
...
...
@@ -10038,6 +10047,7 @@ class UnopNode(ExprNode):
if
self
.
is_cpp_operation
()
and
self
.
exception_check
==
'+'
:
translate_cpp_exception
(
code
,
self
.
pos
,
"%s = %s %s;"
%
(
self
.
result
(),
self
.
operator
,
self
.
operand
.
result
()),
self
.
result
()
if
self
.
type
.
is_pyobject
else
None
,
self
.
exception_value
,
self
.
in_nogil_context
)
else
:
code
.
putln
(
"%s = %s %s;"
%
(
self
.
result
(),
self
.
operator
,
self
.
operand
.
result
()))
...
...
@@ -10277,6 +10287,7 @@ class AmpersandNode(CUnopNode):
if
(
self
.
operand
.
type
.
is_cpp_class
and
self
.
exception_check
==
'+'
):
translate_cpp_exception
(
code
,
self
.
pos
,
"%s = %s %s;"
%
(
self
.
result
(),
self
.
operator
,
self
.
operand
.
result
()),
self
.
result
()
if
self
.
type
.
is_pyobject
else
None
,
self
.
exception_value
,
self
.
in_nogil_context
)
...
...
@@ -10821,7 +10832,7 @@ class TypeidNode(ExprNode):
arg_code
=
self
.
arg_type
.
result
()
translate_cpp_exception
(
code
,
self
.
pos
,
"%s = typeid(%s);"
%
(
self
.
temp_code
,
arg_code
),
None
,
self
.
in_nogil_context
)
None
,
None
,
self
.
in_nogil_context
)
class
TypeofNode
(
ExprNode
):
# Compile-time type of an expression, as a string.
...
...
@@ -11080,6 +11091,7 @@ class BinopNode(ExprNode):
if
self
.
is_cpp_operation
()
and
self
.
exception_check
==
'+'
:
translate_cpp_exception
(
code
,
self
.
pos
,
"%s = %s;"
%
(
self
.
result
(),
self
.
calculate_result_code
()),
self
.
result
()
if
self
.
type
.
is_pyobject
else
None
,
self
.
exception_value
,
self
.
in_nogil_context
)
else
:
code
.
putln
(
"%s = %s;"
%
(
self
.
result
(),
self
.
calculate_result_code
()))
...
...
@@ -12393,7 +12405,13 @@ class CmpNode(object):
self
.
c_operator
(
op
),
code2
)
if
self
.
is_cpp_comparison
()
and
self
.
exception_check
==
'+'
:
translate_cpp_exception
(
code
,
self
.
pos
,
statement
,
self
.
exception_value
,
self
.
in_nogil_context
)
translate_cpp_exception
(
code
,
self
.
pos
,
statement
,
result_code
if
self
.
type
.
is_pyobject
else
None
,
self
.
exception_value
,
self
.
in_nogil_context
)
code
.
putln
(
statement
)
def
c_operator
(
self
,
op
):
...
...
Cython/Compiler/ModuleNode.py
View file @
e2d55c56
...
...
@@ -2238,7 +2238,7 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
code
.
putln
(
"if (0);"
)
# so the first one can be "else if"
msvc_count
=
0
for
name
,
entry
in
sorted
(
env
.
entries
.
items
()):
if
entry
.
is_cglobal
and
entry
.
used
:
if
entry
.
is_cglobal
and
entry
.
used
and
not
entry
.
type
.
is_const
:
msvc_count
+=
1
if
msvc_count
%
100
==
0
:
code
.
putln
(
"#ifdef _MSC_VER"
)
...
...
Cython/Compiler/Nodes.py
View file @
e2d55c56
...
...
@@ -207,6 +207,9 @@ class Node(object):
# can either contain a single node or a list of nodes. See Visitor.py.
child_attrs
=
None
# Subset of attributes that are evaluated in the outer scope (e.g. function default arguments).
outer_attrs
=
None
cf_state
=
None
# This may be an additional (or 'actual') type that will be checked when
...
...
@@ -222,6 +225,7 @@ class Node(object):
gil_message
=
"Operation"
nogil_check
=
None
in_nogil_context
=
False
# For use only during code generation.
def
gil_error
(
self
,
env
=
None
):
error
(
self
.
pos
,
"%s not allowed without gil"
%
self
.
gil_message
)
...
...
@@ -848,6 +852,7 @@ class CArgDeclNode(Node):
# is_dynamic boolean Non-literal arg stored inside CyFunction
child_attrs
=
[
"base_type"
,
"declarator"
,
"default"
,
"annotation"
]
outer_attrs
=
[
"default"
,
"annotation"
]
is_self_arg
=
0
is_type_arg
=
0
...
...
@@ -2335,7 +2340,7 @@ class CFuncDefNode(FuncDefNode):
self
.
is_c_class_method
=
env
.
is_c_class_scope
if
self
.
directive_locals
is
None
:
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
:
base_type
=
self
.
directive_returns
.
analyse_as_type
(
env
)
if
base_type
is
None
:
...
...
@@ -2737,6 +2742,7 @@ class DefNode(FuncDefNode):
# decorator_indirection IndirectionNode Used to remove __Pyx_Method_ClassMethod for fused functions
child_attrs
=
[
"args"
,
"star_arg"
,
"starstar_arg"
,
"body"
,
"decorators"
,
"return_type_annotation"
]
outer_attrs
=
[
"decorators"
,
"return_type_annotation"
]
is_staticmethod
=
False
is_classmethod
=
False
...
...
@@ -2901,7 +2907,7 @@ class DefNode(FuncDefNode):
self
.
py_wrapper
.
analyse_declarations
(
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'
]
f2s
=
env
.
fused_to_specific
...
...
@@ -4953,7 +4959,7 @@ class CClassDefNode(ClassDefNode):
code
.
putln
(
"if (__Pyx_MergeVtables(&%s) < 0) %s"
%
(
typeobj_cname
,
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
# Cython (such as closures), the 'internal'
# directive is set by users
...
...
Cython/Compiler/Options.py
View file @
e2d55c56
...
...
@@ -170,8 +170,6 @@ _directive_defaults = {
'nonecheck'
:
False
,
'initializedcheck'
:
True
,
'embedsignature'
:
False
,
'locals'
:
{},
'exceptval'
:
None
,
# (except value=None, check=True)
'auto_cpdef'
:
False
,
'auto_pickle'
:
None
,
'cdivision'
:
False
,
# was True before 0.12
...
...
@@ -183,12 +181,8 @@ _directive_defaults = {
'wraparound'
:
True
,
'ccomplex'
:
False
,
# use C99/C++ for complex types and arith
'callspec'
:
""
,
'final'
:
False
,
'nogil'
:
False
,
'internal'
:
False
,
'profile'
:
False
,
'no_gc_clear'
:
False
,
'no_gc'
:
False
,
'linetrace'
:
False
,
'emit_code_comments'
:
True
,
# copy original source code into C code comments
'annotation_typing'
:
True
,
# read type declarations from Python function annotations
...
...
@@ -241,7 +235,6 @@ _directive_defaults = {
# experimental, subject to change
'binding'
:
None
,
'freelist'
:
0
,
'formal_grammar'
:
False
,
}
...
...
@@ -301,7 +294,9 @@ def normalise_encoding_name(option_name, encoding):
directive_types
=
{
'language_level'
:
int
,
# values can be None/2/3, where None == 2+warning
'auto_pickle'
:
bool
,
'locals'
:
dict
,
'final'
:
bool
,
# final cdef classes and methods
'nogil'
:
bool
,
'internal'
:
bool
,
# cdef class visibility in the module dict
'infer_types'
:
bool
,
# values can be True/None/False
'binding'
:
bool
,
...
...
@@ -310,7 +305,10 @@ directive_types = {
'inline'
:
None
,
'staticmethod'
:
None
,
'cclass'
:
None
,
'no_gc_clear'
:
bool
,
'no_gc'
:
bool
,
'returns'
:
type
,
'exceptval'
:
type
,
# actually (type, check=True/False), but has its own parser
'set_initial_path'
:
str
,
'freelist'
:
int
,
'c_string_type'
:
one_of
(
'bytes'
,
'bytearray'
,
'str'
,
'unicode'
),
...
...
@@ -325,8 +323,10 @@ directive_scopes = { # defaults to available everywhere
# 'module', 'function', 'class', 'with statement'
'auto_pickle'
:
(
'module'
,
'cclass'
),
'final'
:
(
'cclass'
,
'function'
),
'nogil'
:
(
'function'
,),
'nogil'
:
(
'function'
,
'with statement'
),
'inline'
:
(
'function'
,),
'cfunc'
:
(
'function'
,
'with statement'
),
'ccall'
:
(
'function'
,
'with statement'
),
'returns'
:
(
'function'
,),
'exceptval'
:
(
'function'
,),
'locals'
:
(
'function'
,),
...
...
@@ -334,6 +334,7 @@ directive_scopes = { # defaults to available everywhere
'no_gc_clear'
:
(
'cclass'
,),
'no_gc'
:
(
'cclass'
,),
'internal'
:
(
'cclass'
,),
'cclass'
:
(
'class'
,
'cclass'
,
'with statement'
),
'autotestdict'
:
(
'module'
,),
'autotestdict.all'
:
(
'module'
,),
'autotestdict.cdef'
:
(
'module'
,),
...
...
Cython/Compiler/ParseTreeTransforms.py
View file @
e2d55c56
...
...
@@ -958,30 +958,33 @@ class InterpretCompilerDirectives(CythonTransform):
else
:
assert
False
def
visit_with_directives
(
self
,
body
,
directives
):
olddirectives
=
self
.
directives
newdirectives
=
copy
.
copy
(
olddirectives
)
newdirectives
.
update
(
directives
)
self
.
directives
=
newdirectives
assert
isinstance
(
body
,
Nodes
.
StatListNode
),
body
retbody
=
self
.
visit_Node
(
body
)
directive
=
Nodes
.
CompilerDirectivesNode
(
pos
=
retbody
.
pos
,
body
=
retbody
,
directives
=
newdirectives
)
self
.
directives
=
olddirectives
return
directive
def
visit_with_directives
(
self
,
node
,
directives
):
if
not
directives
:
return
self
.
visit_Node
(
node
)
old_directives
=
self
.
directives
new_directives
=
dict
(
old_directives
)
new_directives
.
update
(
directives
)
if
new_directives
==
old_directives
:
return
self
.
visit_Node
(
node
)
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
def
visit_FuncDefNode
(
self
,
node
):
directives
=
self
.
_extract_directives
(
node
,
'function'
)
if
not
directives
:
return
self
.
visit_Node
(
node
)
body
=
Nodes
.
StatListNode
(
node
.
pos
,
stats
=
[
node
])
return
self
.
visit_with_directives
(
body
,
directives
)
return
self
.
visit_with_directives
(
node
,
directives
)
def
visit_CVarDefNode
(
self
,
node
):
directives
=
self
.
_extract_directives
(
node
,
'function'
)
if
not
directives
:
return
self
.
visit_Node
(
node
)
for
name
,
value
in
directives
.
items
():
if
name
==
'locals'
:
node
.
directive_locals
=
value
...
...
@@ -990,29 +993,19 @@ class InterpretCompilerDirectives(CythonTransform):
node
.
pos
,
"Cdef functions can only take cython.locals(), "
"staticmethod, or final decorators, got %s."
%
name
))
body
=
Nodes
.
StatListNode
(
node
.
pos
,
stats
=
[
node
])
return
self
.
visit_with_directives
(
body
,
directives
)
return
self
.
visit_with_directives
(
node
,
directives
)
def
visit_CClassDefNode
(
self
,
node
):
directives
=
self
.
_extract_directives
(
node
,
'cclass'
)
if
not
directives
:
return
self
.
visit_Node
(
node
)
body
=
Nodes
.
StatListNode
(
node
.
pos
,
stats
=
[
node
])
return
self
.
visit_with_directives
(
body
,
directives
)
return
self
.
visit_with_directives
(
node
,
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
)
return
self
.
visit_with_directives
(
node
,
directives
)
def
visit_PyClassDefNode
(
self
,
node
):
directives
=
self
.
_extract_directives
(
node
,
'class'
)
if
not
directives
:
return
self
.
visit_Node
(
node
)
body
=
Nodes
.
StatListNode
(
node
.
pos
,
stats
=
[
node
])
return
self
.
visit_with_directives
(
body
,
directives
)
return
self
.
visit_with_directives
(
node
,
directives
)
def
_extract_directives
(
self
,
node
,
scope_name
):
if
not
node
.
decorators
:
...
...
@@ -1059,7 +1052,7 @@ class InterpretCompilerDirectives(CythonTransform):
optdict
[
name
]
=
value
return
optdict
# Handle with
statements
# Handle with
-
statements
def
visit_WithStatNode
(
self
,
node
):
directive_dict
=
{}
for
directive
in
self
.
try_to_parse_directives
(
node
.
manager
)
or
[]:
...
...
@@ -2385,6 +2378,10 @@ class AdjustDefByDirectives(CythonTransform, SkipDeclarations):
self
.
visitchildren
(
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
):
if
'cclass'
in
self
.
directives
:
node
=
node
.
as_cclass
()
...
...
@@ -2680,7 +2677,7 @@ class CreateClosureClasses(CythonTransform):
if
node
.
is_generator
:
for
scope
in
node
.
local_scope
.
iter_local_scopes
():
for
entry
in
scope
.
entries
.
values
():
if
not
entry
.
from_closure
:
if
not
(
entry
.
from_closure
or
entry
.
is_pyglobal
or
entry
.
is_cglobal
)
:
entry
.
in_closure
=
True
from_closure
,
in_closure
=
self
.
find_entries_used_in_closures
(
node
)
...
...
@@ -2861,24 +2858,33 @@ class GilCheck(VisitorTransform):
self
.
nogil_declarator_only
=
False
return
super
(
GilCheck
,
self
).
__call__
(
root
)
def
_visit_scoped_children
(
self
,
node
,
gil_state
):
was_nogil
=
self
.
nogil
outer_attrs
=
node
.
outer_attrs
if
outer_attrs
and
len
(
self
.
env_stack
)
>
1
:
self
.
nogil
=
self
.
env_stack
[
-
2
].
nogil
self
.
visitchildren
(
node
,
outer_attrs
)
self
.
nogil
=
gil_state
self
.
visitchildren
(
node
,
exclude
=
outer_attrs
)
self
.
nogil
=
was_nogil
def
visit_FuncDefNode
(
self
,
node
):
self
.
env_stack
.
append
(
node
.
local_scope
)
was_nogil
=
self
.
nogil
self
.
nogil
=
node
.
local_scope
.
nogil
inner_nogil
=
node
.
local_scope
.
nogil
if
self
.
nogil
:
if
inner_
nogil
:
self
.
nogil_declarator_only
=
True
if
self
.
nogil
and
node
.
nogil_check
:
if
inner_
nogil
and
node
.
nogil_check
:
node
.
nogil_check
(
node
.
local_scope
)
self
.
visitchildren
(
node
)
self
.
_visit_scoped_children
(
node
,
inner_nogil
)
# This cannot be nested, so it doesn't need backup/restore
self
.
nogil_declarator_only
=
False
self
.
env_stack
.
pop
()
self
.
nogil
=
was_nogil
return
node
def
visit_GILStatNode
(
self
,
node
):
...
...
@@ -2886,9 +2892,9 @@ class GilCheck(VisitorTransform):
node
.
nogil_check
()
was_nogil
=
self
.
nogil
self
.
nogil
=
(
node
.
state
==
'nogil'
)
is_
nogil
=
(
node
.
state
==
'nogil'
)
if
was_nogil
==
self
.
nogil
and
not
self
.
nogil_declarator_only
:
if
was_nogil
==
is_
nogil
and
not
self
.
nogil_declarator_only
:
if
not
was_nogil
:
error
(
node
.
pos
,
"Trying to acquire the GIL while it is "
"already held."
)
...
...
@@ -2901,8 +2907,7 @@ class GilCheck(VisitorTransform):
# which is wrapped in a StatListNode. Just unpack that.
node
.
finally_clause
,
=
node
.
finally_clause
.
stats
self
.
visitchildren
(
node
)
self
.
nogil
=
was_nogil
self
.
_visit_scoped_children
(
node
,
is_nogil
)
return
node
def
visit_ParallelRangeNode
(
self
,
node
):
...
...
@@ -2949,8 +2954,12 @@ class GilCheck(VisitorTransform):
def
visit_Node
(
self
,
node
):
if
self
.
env_stack
and
self
.
nogil
and
node
.
nogil_check
:
node
.
nogil_check
(
self
.
env_stack
[
-
1
])
self
.
visitchildren
(
node
)
node
.
in_nogil_context
=
self
.
nogil
if
node
.
outer_attrs
:
self
.
_visit_scoped_children
(
node
,
self
.
nogil
)
else
:
self
.
visitchildren
(
node
)
if
self
.
nogil
:
node
.
in_nogil_context
=
True
return
node
...
...
Cython/Compiler/Visitor.pxd
View file @
e2d55c56
...
...
@@ -16,8 +16,9 @@ cdef class TreeVisitor:
cdef
class
VisitorTransform
(
TreeVisitor
):
cdef
dict
_process_children
(
self
,
parent
,
attrs
=*
)
cpdef
visitchildren
(
self
,
parent
,
attrs
=*
)
cpdef
visitchildren
(
self
,
parent
,
attrs
=*
,
exclude
=*
)
cdef
list
_flatten_list
(
self
,
list
orig_list
)
cdef
list
_select_attrs
(
self
,
attrs
,
exclude
)
cdef
class
CythonTransform
(
VisitorTransform
):
cdef
public
context
...
...
Cython/Compiler/Visitor.py
View file @
e2d55c56
...
...
@@ -244,10 +244,16 @@ class VisitorTransform(TreeVisitor):
was not, an exception will be raised. (Typically you want to ensure that you
are within a StatListNode or similar before doing this.)
"""
def
visitchildren
(
self
,
parent
,
attrs
=
None
):
def
visitchildren
(
self
,
parent
,
attrs
=
None
,
exclude
=
None
):
# generic def entry point for calls from Python subclasses
if
exclude
is
not
None
:
attrs
=
self
.
_select_attrs
(
parent
.
child_attrs
if
attrs
is
None
else
attrs
,
exclude
)
return
self
.
_process_children
(
parent
,
attrs
)
@
cython
.
final
def
_select_attrs
(
self
,
attrs
,
exclude
):
return
[
name
for
name
in
attrs
if
name
not
in
exclude
]
@
cython
.
final
def
_process_children
(
self
,
parent
,
attrs
=
None
):
# fast cdef entry point for calls from Cython subclasses
...
...
Cython/Includes/libc/math.pxd
View file @
e2d55c56
cdef
extern
from
"<math.h>"
nogil
:
double
M_E
double
e
"M_E"
# as in Python's math module
double
M_LOG2E
double
M_LOG10E
double
M_LN2
double
M_LN10
double
M_PI
double
pi
"M_PI"
# as in Python's math module
double
M_PI_2
double
M_PI_4
double
M_1_PI
double
M_2_PI
double
M_2_SQRTPI
double
M_SQRT2
double
M_SQRT1_2
const
double
M_E
const
double
e
"M_E"
# as in Python's math module
const
double
M_LOG2E
const
double
M_LOG10E
const
double
M_LN2
const
double
M_LN10
const
double
M_PI
const
double
pi
"M_PI"
# as in Python's math module
const
double
M_PI_2
const
double
M_PI_4
const
double
M_1_PI
const
double
M_2_PI
const
double
M_2_SQRTPI
const
double
M_SQRT2
const
double
M_SQRT1_2
# C99 constants
float
INFINITY
float
NAN
const
float
INFINITY
const
float
NAN
# note: not providing "nan" and "inf" aliases here as nan() is a function in C
double
HUGE_VAL
float
HUGE_VALF
long
double
HUGE_VALL
const
double
HUGE_VAL
const
float
HUGE_VALF
const
long
double
HUGE_VALL
double
acos
(
double
x
)
double
asin
(
double
x
)
...
...
Cython/Shadow.py
View file @
e2d55c56
...
...
@@ -455,7 +455,7 @@ class CythonDotParallel(object):
def
parallel
(
self
,
num_threads
=
None
):
return
nogil
def
prange
(
self
,
start
=
0
,
stop
=
None
,
step
=
1
,
schedule
=
None
,
nogil
=
Fals
e
):
def
prange
(
self
,
start
=
0
,
stop
=
None
,
step
=
1
,
nogil
=
False
,
schedule
=
None
,
chunksize
=
None
,
num_threads
=
Non
e
):
if
stop
is
None
:
stop
=
start
start
=
0
...
...
Cython/Utility/TypeConversion.c
View file @
e2d55c56
...
...
@@ -376,7 +376,7 @@ static CYTHON_INLINE Py_ssize_t __Pyx_PyIndex_AsSsize_t(PyObject* b) {
if
(
sizeof
(
Py_ssize_t
)
>=
sizeof
(
long
))
return
PyInt_AS_LONG
(
b
);
else
return
PyInt_AsSsize_t
(
x
);
return
PyInt_AsSsize_t
(
b
);
}
#endif
if
(
likely
(
PyLong_CheckExact
(
b
)))
{
...
...
tests/memoryview/memoryview_annotation_typing.py
View file @
e2d55c56
...
...
@@ -34,3 +34,21 @@ def two_dim(a: cython.double[:,:]):
"""
a
[
0
,
0
]
*=
3
return
a
[
0
,
0
],
a
[
0
,
1
],
a
.
ndim
@
cython
.
nogil
@
cython
.
cfunc
def
_one_dim_nogil_cfunc
(
a
:
cython
.
double
[:])
->
cython
.
double
:
a
[
0
]
*=
2
return
a
[
0
]
def
one_dim_nogil_cfunc
(
a
:
cython
.
double
[:]):
"""
>>> a = numpy.ones((10,), numpy.double)
>>> one_dim_nogil_cfunc(a)
2.0
"""
with
cython
.
nogil
:
result
=
_one_dim_nogil_cfunc
(
a
)
return
result
tests/run/async_globals.pyx
0 → 100644
View file @
e2d55c56
# mode: run
# tag: pep492, asyncfor, await, gh2613
# Using C-globals in coroutines.
cdef
object
py_retval
async
def
test
():
"""
>>> t = test()
>>> try: t.send(None)
... except StopIteration as ex:
... print(ex.args[0] if ex.args else None)
... else: print("NOT STOPPED!")
None
"""
global
py_retval
py_retval
=
{
'foo'
:
42
}
tests/run/cpp_exceptions.pyx
View file @
e2d55c56
...
...
@@ -21,6 +21,8 @@ cdef extern from "cpp_exceptions_helper.h":
cdef
void
raise_typeerror
()
except
+
cdef
void
raise_underflow
()
except
+
cdef
raise_or_throw
(
bint
py
)
except
+
cdef
cppclass
Foo
:
int
bar_raw
"bar"
(
bint
fire
)
except
+
int
bar_value
"bar"
(
bint
fire
)
except
+
ValueError
...
...
@@ -98,6 +100,19 @@ def test_underflow():
"""
raise_underflow
()
def
test_func_that_can_raise_or_throw
(
bint
py
):
"""
>>> test_func_that_can_raise_or_throw(0)
Traceback (most recent call last):
...
RuntimeError: oopsie
>>> test_func_that_can_raise_or_throw(1)
Traceback (most recent call last):
...
ValueError: oopsie
"""
raise_or_throw
(
py
)
def
test_int_raw
(
bint
fire
):
"""
>>> test_int_raw(False)
...
...
tests/run/cpp_exceptions_helper.h
View file @
e2d55c56
#include <Python.h>
#include <ios>
#include <new>
#include <stdexcept>
...
...
@@ -61,3 +62,11 @@ void raise_typeerror() {
void
raise_underflow
()
{
throw
std
::
underflow_error
(
"underflow_error"
);
}
PyObject
*
raise_or_throw
(
int
py
)
{
if
(
!
py
)
{
throw
std
::
runtime_error
(
"oopsie"
);
}
PyErr_SetString
(
PyExc_ValueError
,
"oopsie"
);
return
NULL
;
}
tests/run/exttype_freelist.pyx
View file @
e2d55c56
...
...
@@ -451,3 +451,19 @@ cdef class ExtTypeWithRefCycle:
def
__init__
(
self
,
obj
=
None
):
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/import_star.pyx
View file @
e2d55c56
...
...
@@ -10,7 +10,9 @@ ctypedef struct MyStruct:
# (there used to be a problem getting Cython conversion code generated here)
cdef
MyStruct
_no_such_name_
=
MyStruct
(
1
,
2
,
3
)
from
libc.math
cimport
NAN
# Danger ahead!
from
sys
import
*
...
...
@@ -39,3 +41,13 @@ def test_non_cdefed_names():
>>> assert pth is not None
"""
return
modules
,
path
def
test_cimported_NAN
():
"""
>>> from math import isnan
>>> nan = test_cimported_NAN()
>>> isnan(nan)
True
"""
return
NAN
tests/run/pure_parallel.py
0 → 100644
View file @
e2d55c56
# mode: run
# tag: openmp, pure3.6
import
cython
from
cython.parallel
import
prange
,
parallel
def
prange_regression
(
n
:
cython
.
int
,
data
:
list
):
"""
>>> prange_regression(10, list(range(1, 4)))
19
"""
s
:
cython
.
int
=
0
i
:
cython
.
int
d
:
cython
.
int
[
3
]
=
data
for
i
in
prange
(
n
,
num_threads
=
3
,
nogil
=
True
):
s
+=
d
[
i
%
3
]
return
s
def
prange_with_gil
(
n
:
cython
.
int
,
x
):
"""
>>> sum(3*i for i in range(10))
135
>>> prange_with_gil(10, 3)
135
"""
i
:
cython
.
int
s
:
cython
.
int
=
0
for
i
in
prange
(
n
,
num_threads
=
3
,
nogil
=
True
):
with
cython
.
gil
:
s
+=
x
*
i
return
s
@
cython
.
cfunc
def
use_nogil
(
x
,
i
:
cython
.
int
)
->
cython
.
int
:
cx
:
cython
.
int
=
x
with
cython
.
nogil
:
return
cx
*
i
def
prange_with_gil_call_nogil
(
n
:
cython
.
int
,
x
):
"""
>>> sum(3*i for i in range(10))
135
>>> prange_with_gil(10, 3)
135
"""
i
:
cython
.
int
s
:
cython
.
int
=
0
for
i
in
prange
(
n
,
num_threads
=
3
,
nogil
=
True
):
with
cython
.
gil
:
s
+=
use_nogil
(
x
,
i
)
return
s
tests/run/purecdef.py
View file @
e2d55c56
...
...
@@ -28,6 +28,17 @@ with cfunc:
def
fwith2
(
a
):
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
:
@
cython
.
test_assert_path_exists
(
'//CClassDefNode'
)
class
Egg
(
object
):
...
...
@@ -123,3 +134,14 @@ def test_typed_return():
"""
x
=
cython
.
declare
(
int
,
5
)
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