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
f18e3c9f
Commit
f18e3c9f
authored
Apr 18, 2020
by
da-woods
Committed by
GitHub
Apr 18, 2020
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Make "cimport numpy" without import_array() safer by automatically calling it (GH-3524)
parent
3a3419fb
Changes
12
Show whitespace changes
Inline
Side-by-side
Showing
12 changed files
with
200 additions
and
8 deletions
+200
-8
CHANGES.rst
CHANGES.rst
+5
-0
Cython/Compiler/Nodes.py
Cython/Compiler/Nodes.py
+31
-2
Cython/Compiler/TypeInference.py
Cython/Compiler/TypeInference.py
+1
-1
Cython/Includes/numpy/__init__.pxd
Cython/Includes/numpy/__init__.pxd
+4
-1
Cython/Utility/NumpyImportArray.c
Cython/Utility/NumpyImportArray.c
+21
-0
tests/errors/w_numpy_arr_as_cppvec_ref.pyx
tests/errors/w_numpy_arr_as_cppvec_ref.pyx
+6
-4
tests/run/numpy_cimport_1.pyx
tests/run/numpy_cimport_1.pyx
+25
-0
tests/run/numpy_cimport_2.pyx
tests/run/numpy_cimport_2.pyx
+25
-0
tests/run/numpy_cimport_3.pyx
tests/run/numpy_cimport_3.pyx
+8
-0
tests/run/numpy_cimport_4.pyx
tests/run/numpy_cimport_4.pyx
+24
-0
tests/run/numpy_cimport_5.pyx
tests/run/numpy_cimport_5.pyx
+25
-0
tests/run/numpy_cimport_6.pyx
tests/run/numpy_cimport_6.pyx
+25
-0
No files found.
CHANGES.rst
View file @
f18e3c9f
...
...
@@ -234,6 +234,11 @@ Other changes
* Support for Python 2.6 was removed.
* ``numpy.import_array`` is automatically called if ``numpy`` has been
``cimported`` and it hasn'
t
been
called
manually
.
This
is
intended
as
a
hidden
fail
-
safe
so
user
code
should
continue
to
call
``
numpy
.
import_array
``.
(
Github
issue
#
3524
)
0.29.17
(
2020
-
0
?-??)
====================
...
...
Cython/Compiler/Nodes.py
View file @
f18e3c9f
...
...
@@ -8159,6 +8159,33 @@ utility_code_for_imports = {
'inspect'
:
(
"__Pyx_patch_inspect"
,
"PatchInspect"
,
"Coroutine.c"
),
}
def
cimport_numpy_check
(
node
,
code
):
# shared code between CImportStatNode and FromCImportStatNode
# check to ensure that import_array is called
for
mod
in
code
.
globalstate
.
module_node
.
scope
.
cimported_modules
:
if
mod
.
name
!=
node
.
module_name
:
continue
# there are sometimes several cimported modules with the same name
# so complete the loop if necessary
import_array
=
mod
.
lookup_here
(
"import_array"
)
_import_array
=
mod
.
lookup_here
(
"_import_array"
)
# at least one entry used
used
=
(
import_array
and
import_array
.
used
)
or
(
_import_array
and
_import_array
.
used
)
if
((
import_array
or
_import_array
)
# at least one entry found
and
not
used
):
# sanity check that this is actually numpy and not a user pxd called "numpy"
if
_import_array
and
_import_array
.
type
.
is_cfunction
:
# warning is mainly for the sake of testing
warning
(
node
.
pos
,
"'numpy.import_array()' has been added automatically "
"since 'numpy' was cimported but 'numpy.import_array' was not called."
,
0
)
from
.Code
import
TempitaUtilityCode
code
.
globalstate
.
use_utility_code
(
TempitaUtilityCode
.
load_cached
(
"NumpyImportArray"
,
"NumpyImportArray.c"
,
context
=
{
'err_goto'
:
code
.
error_goto
(
node
.
pos
)})
)
return
# no need to continue once the utility code is added
class
CImportStatNode
(
StatNode
):
# cimport statement
...
...
@@ -8200,7 +8227,8 @@ class CImportStatNode(StatNode):
return
self
def
generate_execution_code
(
self
,
code
):
pass
if
self
.
module_name
==
"numpy"
:
cimport_numpy_check
(
self
,
code
)
class
FromCImportStatNode
(
StatNode
):
...
...
@@ -8279,7 +8307,8 @@ class FromCImportStatNode(StatNode):
return
self
def
generate_execution_code
(
self
,
code
):
pass
if
self
.
module_name
==
"numpy"
:
cimport_numpy_check
(
self
,
code
)
class
FromImportStatNode
(
StatNode
):
...
...
Cython/Compiler/TypeInference.py
View file @
f18e3c9f
...
...
@@ -178,7 +178,7 @@ class MarkParallelAssignments(EnvTransform):
return
node
def
visit_FromCImportStatNode
(
self
,
node
):
pass
# Can't be assigned to...
return
node
# Can't be assigned to...
def
visit_FromImportStatNode
(
self
,
node
):
for
name
,
target
in
node
.
items
:
...
...
Cython/Includes/numpy/__init__.pxd
View file @
f18e3c9f
...
...
@@ -430,6 +430,9 @@ cdef extern from "numpy/arrayobject.h":
int
len
int
_import_array
()
except
-
1
# A second definition so _import_array isn't marked as used when we use it here.
# Do not use - subject to change any time.
int
__pyx_import_array
"_import_array"
()
except
-
1
#
# Macros from ndarrayobject.h
...
...
@@ -1046,7 +1049,7 @@ cdef inline object get_array_base(ndarray arr):
# Cython code.
cdef
inline
int
import_array
()
except
-
1
:
try
:
_import_array
()
_
_pyx_
import_array
()
except
Exception
:
raise
ImportError
(
"numpy.core.multiarray failed to import"
)
...
...
Cython/Utility/NumpyImportArray.c
0 → 100644
View file @
f18e3c9f
///////////////////////// NumpyImportArray.init ////////////////////
// comment below is deliberately kept in the generated C file to
// help users debug where this came from:
/*
* Cython has automatically inserted a call to _import_array since
* you didn't include one when you cimported numpy. To disable this
* add the line
* <void>numpy._import_array
*/
#ifdef NPY_NDARRAYOBJECT_H
/* numpy headers have been included */
// NO_IMPORT_ARRAY is Numpy's mechanism for indicating that import_array is handled elsewhere
#if !NO_IMPORT_ARRAY
/* https://docs.scipy.org/doc/numpy-1.17.0/reference/c-api.array.html#c.NO_IMPORT_ARRAY */
if
(
unlikely
(
_import_array
()
==
-
1
))
{
PyErr_SetString
(
PyExc_ImportError
,
"numpy.core.multiarray failed to import "
"(auto-generated because you didn't call 'numpy.import_array()' after cimporting numpy; "
"use '<void>numpy._import_array' to disable if you are certain you don't need it)."
);
{{
err_goto
}};
}
#endif
#endif
tests/errors/w_numpy_arr_as_cppvec_ref.pyx
View file @
f18e3c9f
...
...
@@ -5,6 +5,8 @@ import numpy as np
cimport
numpy
as
np
from
libcpp.vector
cimport
vector
np
.
import_array
()
cdef
extern
from
*
:
void
cpp_function_vector1
(
vector
[
int
])
void
cpp_function_vector2
(
vector
[
int
]
&
)
...
...
@@ -24,8 +26,8 @@ def main():
_ERRORS
=
"""
1
7
:25: Cannot pass Python object as C++ data structure reference (vector[int] &), will pass by copy.
18
:25: Cannot pass Python object as C++ data structure reference (vector[int] &), will pass by copy.
19
:28: Cannot pass Python object as C++ data structure reference (vector[int] &), will pass by copy.
19
:33: Cannot pass Python object as C++ data structure reference (vector[int] &), will pass by copy.
1
9
:25: Cannot pass Python object as C++ data structure reference (vector[int] &), will pass by copy.
20
:25: Cannot pass Python object as C++ data structure reference (vector[int] &), will pass by copy.
21
:28: Cannot pass Python object as C++ data structure reference (vector[int] &), will pass by copy.
21
:33: Cannot pass Python object as C++ data structure reference (vector[int] &), will pass by copy.
"""
tests/run/numpy_cimport_1.pyx
0 → 100644
View file @
f18e3c9f
# mode: run
# tag: warnings, numpy
cimport
numpy
as
np
# np.import_array not called - should generate warning
cdef
extern
from
*
:
"""
static void** _check_array_api(void) {
return PyArray_API; /* should be non NULL */
}
"""
void
**
_check_array_api
()
def
check_array_api
():
"""
>>> check_array_api()
True
"""
return
_check_array_api
()
!=
NULL
_WARNINGS
=
"""
4:8: 'numpy.import_array()' has been added automatically since 'numpy' was cimported but 'numpy.import_array' was not called.
"""
tests/run/numpy_cimport_2.pyx
0 → 100644
View file @
f18e3c9f
# mode: run
# tag: warnings, numpy
cimport
numpy
as
np
np
.
import_array
()
# np.import_array is called - no warning necessary
cdef
extern
from
*
:
"""
static void** _check_array_api(void) {
return PyArray_API; /* should be non NULL */
}
"""
void
**
_check_array_api
()
def
check_array_api
():
"""
>>> check_array_api()
True
"""
return
_check_array_api
()
!=
NULL
_WARNINGS
=
"""
"""
tests/run/numpy_cimport_3.pyx
0 → 100644
View file @
f18e3c9f
# mode: compile
# tag: warnings, numpy
import
numpy
as
np
# Numpy is only imported - no warning necessary
_WARNINGS
=
"""
"""
tests/run/numpy_cimport_4.pyx
0 → 100644
View file @
f18e3c9f
# mode: run
# tag: warnings, numpy
cimport
numpy
<
void
>
numpy
.
import_array
# dummy call should stop Cython auto-generating call to import_array
cdef
extern
from
*
:
"""
static void** _check_array_api(void) {
return PyArray_API; /* should be non NULL if initialized */
}
"""
void
**
_check_array_api
()
def
check_array_api
():
"""
>>> check_array_api()
True
"""
return
_check_array_api
()
==
NULL
# not initialized
_WARNINGS
=
"""
"""
tests/run/numpy_cimport_5.pyx
0 → 100644
View file @
f18e3c9f
# mode: run
# tag: warnings, numpy
from
numpy
cimport
ndarray
# np.import_array not called - should generate warning
cdef
extern
from
*
:
"""
static void** _check_array_api(void) {
return PyArray_API; /* should be non NULL */
}
"""
void
**
_check_array_api
()
def
check_array_api
():
"""
>>> check_array_api()
True
"""
return
_check_array_api
()
!=
NULL
_WARNINGS
=
"""
4:0: 'numpy.import_array()' has been added automatically since 'numpy' was cimported but 'numpy.import_array' was not called.
"""
tests/run/numpy_cimport_6.pyx
0 → 100644
View file @
f18e3c9f
# mode: run
# tag: warnings, numpy
from
numpy
cimport
ndarray
,
import_array
import_array
()
# np.import_array is called - no warning necessary
cdef
extern
from
*
:
"""
static void** _check_array_api(void) {
return PyArray_API; /* should be non NULL */
}
"""
void
**
_check_array_api
()
def
check_array_api
():
"""
>>> check_array_api()
True
"""
return
_check_array_api
()
!=
NULL
_WARNINGS
=
"""
"""
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