Skip to content

Commit

Permalink
ENH: provide a convenience function to replace npy_load_module (numpy…
Browse files Browse the repository at this point in the history
…#20395)

`load_module` is deprecated since python 3.4 and will be removed in python 3.12.
Use `exec_module` instead. Provide a convenience function in `distutils.misc_utils`
instead of `npy_load_module` from `compat.py3k`.
  • Loading branch information
mattip committed Nov 19, 2021
1 parent 3774a62 commit 46ec71f
Show file tree
Hide file tree
Showing 5 changed files with 28 additions and 17 deletions.
4 changes: 3 additions & 1 deletion numpy/compat/py3k.py
Expand Up @@ -107,7 +107,9 @@ def __exit__(self, *excinfo):

def npy_load_module(name, fn, info=None):
"""
Load a module.
Load a module. Uses ``load_module`` which will be deprecated in python
3.12. An alternative that uses ``exec_module`` is in
numpy.distutils.misc_util.exec_mod_from_location
.. versionadded:: 1.11.2
Expand Down
4 changes: 2 additions & 2 deletions numpy/distutils/ccompiler_opt.py
Expand Up @@ -654,9 +654,9 @@ def dist_log(*args, stderr=False):
@staticmethod
def dist_load_module(name, path):
"""Load a module from file, required by the abstract class '_Cache'."""
from numpy.compat import npy_load_module
from .misc_util import exec_mod_from_location
try:
return npy_load_module(name, path)
return exec_mod_from_location(name, path)
except Exception as e:
_Distutils.dist_log(e, stderr=True)
return None
Expand Down
25 changes: 17 additions & 8 deletions numpy/distutils/misc_util.py
Expand Up @@ -31,8 +31,6 @@ def clean_up_temporary_directory():

atexit.register(clean_up_temporary_directory)

from numpy.compat import npy_load_module

__all__ = ['Configuration', 'get_numpy_include_dirs', 'default_config_dict',
'dict_append', 'appendpath', 'generate_config_py',
'get_cmd', 'allpath', 'get_mathlibs',
Expand All @@ -44,7 +42,8 @@ def clean_up_temporary_directory():
'dot_join', 'get_frame', 'minrelpath', 'njoin',
'is_sequence', 'is_string', 'as_list', 'gpaths', 'get_language',
'get_build_architecture', 'get_info', 'get_pkg_info',
'get_num_build_jobs', 'sanitize_cxx_flags']
'get_num_build_jobs', 'sanitize_cxx_flags',
'exec_mod_from_location']

class InstallableLib:
"""
Expand Down Expand Up @@ -945,9 +944,8 @@ def _get_configuration_from_setup_py(self, setup_py,
try:
setup_name = os.path.splitext(os.path.basename(setup_py))[0]
n = dot_join(self.name, subpackage_name, setup_name)
setup_module = npy_load_module('_'.join(n.split('.')),
setup_py,
('.py', 'U', 1))
setup_module = exec_mod_from_location(
'_'.join(n.split('.')), setup_py)
if not hasattr(setup_module, 'configuration'):
if not self.options['assume_default_configuration']:
self.warn('Assuming default configuration '\
Expand Down Expand Up @@ -1993,8 +1991,8 @@ def get_version(self, version_file=None, version_variable=None):
name = os.path.splitext(os.path.basename(fn))[0]
n = dot_join(self.name, name)
try:
version_module = npy_load_module('_'.join(n.split('.')),
fn, info)
version_module = exec_mod_from_location(
'_'.join(n.split('.')), fn)
except ImportError as e:
self.warn(str(e))
version_module = None
Expand Down Expand Up @@ -2491,3 +2489,14 @@ def sanitize_cxx_flags(cxxflags):
return [flag for flag in cxxflags if flag not in _cxx_ignore_flags]


def exec_mod_from_location(modname, modfile):
'''
Use importlib machinery to import a module `modname` from the file
`modfile`. Depending on the `spec.loader`, the module may not be
registered in sys.modules.
'''
spec = importlib.util.spec_from_file_location(modname, modfile)
foo = importlib.util.module_from_spec(spec)
spec.loader.exec_module(foo)
return foo

8 changes: 4 additions & 4 deletions numpy/random/tests/test_extending.py
Expand Up @@ -5,6 +5,7 @@
import sys
import warnings
import numpy as np
from numpy.distutils.misc_util import exec_mod_from_location

try:
import cffi
Expand Down Expand Up @@ -75,10 +76,9 @@ def test_cython(tmp_path):
assert so1 is not None
assert so2 is not None
# import the so's without adding the directory to sys.path
from importlib.machinery import ExtensionFileLoader
extending = ExtensionFileLoader('extending', so1).load_module()
extending_distributions = ExtensionFileLoader('extending_distributions', so2).load_module()

exec_mod_from_location('extending', so1)
extending_distributions = exec_mod_from_location(
'extending_distributions', so2)
# actually test the cython c-extension
from numpy.random import PCG64
values = extending_distributions.uniforms_ex(PCG64(0), 10, 'd')
Expand Down
4 changes: 2 additions & 2 deletions numpy/testing/_private/utils.py
Expand Up @@ -1228,13 +1228,13 @@ def rundocs(filename=None, raise_on_error=True):
>>> np.lib.test(doctests=True) # doctest: +SKIP
"""
from numpy.compat import npy_load_module
from numpy.distutils.misc_util import exec_mod_from_location
import doctest
if filename is None:
f = sys._getframe(1)
filename = f.f_globals['__file__']
name = os.path.splitext(os.path.basename(filename))[0]
m = npy_load_module(name, filename)
m = exec_mod_from_location(name, filename)

tests = doctest.DocTestFinder().find(m)
runner = doctest.DocTestRunner(verbose=False)
Expand Down

0 comments on commit 46ec71f

Please sign in to comment.