10BC0 Merge pull request #7941 from charris/fix-numpy-reload-again · numpy/numpy@276423a · GitHub
[go: up one dir, main page]

Skip to content

Commit 276423a

Browse files
authored
Merge pull request #7941 from charris/fix-numpy-reload-again
BUG: Make sure numpy globals keep identity after reload.
2 parents 86960c2 + 0ade4c4 commit 276423a

File tree

3 files changed

+81
-53
lines changed

3 files changed

+81
-53
lines changed

numpy/__init__.py

Lines changed: 8 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -109,56 +109,8 @@
109109
import sys
110110
import warnings
111111

112-
# Disallow reloading numpy. Doing that does nothing to change previously
113-
# loaded modules, which would need to be reloaded separately, but it does
114-
# change the identity of the warnings and sentinal classes defined below
115-
# with dire consequences when checking for identity.
116-
if '_is_loaded' in globals():
117-
raise RuntimeError('Reloading numpy is not supported')
118-
_is_loaded = True
119-
120-
121-
# Define some global warnings and the _NoValue sentinal. Defining them here
122-
# means that their identity will change if numpy is reloaded, hence if that is
123-
# to be allowed they should be moved into their own, non-reloadable module.
124-
# Note that these should be defined (or imported) before the other imports.
125-
class ModuleDeprecationWarning(DeprecationWarning):
126-
"""Module deprecation warning.
127-
128-
The nose tester turns ordinary Deprecation warnings into test failures.
129-
That makes it hard to deprecate whole modules, because they get
130-
imported by default. So this is a special Deprecation warning that the
131-
nose tester will let pass without making tests fail.
132-
133-
"""
134-
pass
135-
136-
137-
class VisibleDeprecationWarning(UserWarning):
138-
"""Visible deprecation warning.
139-
140-
By default, python will not show deprecation warnings, so this class
141-
can be used when a very visible warning is helpful, for example because
142-
the usage is most likely a user bug.
143-
144-
"""
145-
pass
146-
147-
148-
class _NoValue:
149-
"""Special keyword value.
150-
151-
This class may be used as the default value assigned to a deprecated
152-
keyword in order to check if it has been given a user defined value.
153-
"""
154-
pass
155-
156-
157-
# oldnumeric and numarray were removed in 1.9. In case some packages import
158-
# but do not use them, we define them here for backward compatibility.
159-
oldnumeric = 'removed'
160-
numarray = 'removed'
161-
112+
from ._globals import ModuleDeprecationWarning, VisibleDeprecationWarning
113+
from ._globals import _NoValue
162114

163115
# We first need to detect if we're being called as part of the numpy setup
164116
# procedure itself in a reliable manner.
@@ -177,6 +129,7 @@ class _NoValue:
177129
its source directory; please exit the numpy source tree, and relaunch
178130
your python interpreter from there."""
179131
raise ImportError(msg)
132+
180133
from .version import git_revision as __git_revision__
181134
from .version import version as __version__
182135

@@ -239,3 +192,8 @@ def pkgload(*packages, **options):
239192
warnings.filterwarnings("ignore", message="numpy.dtype size changed")
240193
warnings.filterwarnings("ignore", message="numpy.ufunc size changed")
241194
warnings.filterwarnings("ignore", message="numpy.ndarray size changed")
195+
196+
# oldnumeric and numarray were removed in 1.9. In case some packages import
197+
# but do not use them, we define them here for backward compatibility.
198+
oldnumeric = 'removed'
199+
numarray = 'removed'

numpy/_globals.py

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
"""
2+
Module defining global singleton classes.
3+
4+
This module raises a RuntimeError if an attempt to reload it is made. In that
5+
way the identities of the classes defined here are fixed and will remain so
6+
even if numpy itself is reloaded. In particular, a function like the following
7+
will still work correctly after numpy is reloaded::
8+
9+
def foo(arg=np._NoValue):
10+
if arg is np._NoValue:
11+
...
12+
13+
That was not the case when the singleton classes were defined in the numpy
14+
``__init__.py`` file. See gh-7844 for a discussion of the reload problem that
15+
motivated this module.
16+
17+
"""
18+
from __future__ import division, absolute_import, print_function
19+
20+
21+
__ALL__ = [
22+
'ModuleDeprecationWarning', 'VisibleDeprecationWarning', '_NoValue'
23+
]
24+
25+
26+
# Disallow reloading this module so as to preserve the identities of the
27+
# classes defined here.
28+
if '_is_loaded' in globals():
29+
raise RuntimeError('Reloading numpy._globals is not allowed')
30+
_is_loaded = True
31+
32+
33+
class ModuleDeprecationWarning(DeprecationWarning):
34+
"""Module deprecation warning.
35+
36+
The nose tester turns ordinary Deprecation warnings into test failures.
37+
That makes it hard to deprecate whole modules, because they get
38+
imported by default. So this is a special Deprecation warning that the
39+
nose tester will let pass without making tests fail.
40+
41+
"""
42+
pass
43+
44+
45+
class VisibleDeprecationWarning(UserWarning):
46+
"""Visible deprecation warning.
47+
48+
By default, python will not show deprecation warnings, so this class
49+
can be used when a very visible warning is helpful, for example because
50+
the usage is most likely a user bug.
51+
52+
"""
53+
pass
54+
55+
56+
class _NoValue:
57+
"""Special keyword value.
58+
59+
This class may be used as the default value assigned to a deprecated
60+
keyword in order to check if it has been given a user defined value.
61+
"""
62+
pass

numpy/tests/test_reloading.py

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,21 +2,29 @@
22

33
import sys
44

5-
import numpy as np
65
from numpy.testing import assert_raises, assert_, run_module_suite
76

87
if sys.version_info[:2] >= (3, 4):
98
from importlib import reload
109
else:
1110
from imp import reload
1211

13-
def test_reloading_exception():
12+
def test_numpy_reloading():
1413
# gh-7844. Also check that relevant globals retain their identity.
14+
import numpy as np
15+
import numpy._globals
16+
1517
_NoValue = np._NoValue
1618
VisibleDeprecationWarning = np.VisibleDeprecationWarning
1719
ModuleDeprecationWarning = np.ModuleDeprecationWarning
1820

19-
assert_raises(RuntimeError, reload, np)
21+
reload(np)
22+
assert_(_NoValue is np._NoValue)
23+
assert_(ModuleDeprecationWarning is np.ModuleDeprecationWarning)
24+
assert_(VisibleDeprecationWarning is np.VisibleDeprecationWarning)
25+
26+
assert_raises(RuntimeError, reload, numpy._globals)
27+
reload(np)
2028
assert_(_NoValue is np._NoValue)
2129
assert_(ModuleDeprecationWarning is np.ModuleDeprecationWarning)
2230
assert_(VisibleDeprecationWarning is np.VisibleDeprecationWarning)

0 commit comments

Comments
 (0)
0