From 09a570e1efe6fb45c01fc8dc96d64a799ab879ee Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Wed, 6 May 2020 10:22:06 -0500 Subject: [PATCH 1/2] Restore numba.types as public API --- numba/tests/test_moved_modules.py | 21 +++++++++++++++++++++ numba/types/__init__.py | 3 +++ 2 files changed, 24 insertions(+) create mode 100644 numba/tests/test_moved_modules.py create mode 100644 numba/types/__init__.py diff --git a/numba/tests/test_moved_modules.py b/numba/tests/test_moved_modules.py new file mode 100644 index 00000000000..81e61a2f108 --- /dev/null +++ b/numba/tests/test_moved_modules.py @@ -0,0 +1,21 @@ +"""Tests for moved modules and their redirection from old path +""" +from numba.tests.support import TestCase + + +class TestMovedModule(TestCase): + """Testing moved modules in Q1 2020 but were decided to kept as public API + """ + def tests_numba_types(self): + import numba.types + import numba.core.types as types + # The old module is the new module + self.assertIs(numba.types, types) + # Attribute access are there + self.assertIs(numba.types.intp, types.intp) + self.assertIs(numba.types.float64, types.float64) + self.assertIs(numba.types.Array, types.Array) + # Submodule access through old import path is possible + import numba.types.misc + self.assertIs(types.misc, numba.types.misc) + self.assertIs(types.misc.Optional, numba.types.misc.Optional) diff --git a/numba/types/__init__.py b/numba/types/__init__.py new file mode 100644 index 00000000000..cab9204c75c --- /dev/null +++ b/numba/types/__init__.py @@ -0,0 +1,3 @@ +import sys +import numba.core.types +sys.modules[__name__] = numba.core.types From 2998661e6f33d8b437aadd70f0b0f08302524b0e Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Wed, 6 May 2020 12:05:44 -0500 Subject: [PATCH 2/2] A better subpackage redirection --- numba/core/utils.py | 36 +++++++++++++++++++++++++++++++ numba/tests/test_moved_modules.py | 13 +++++++++-- numba/types/__init__.py | 5 +++-- 3 files changed, 50 insertions(+), 4 deletions(-) diff --git a/numba/core/utils.py b/numba/core/utils.py index b5703de5e19..9909f85ae4e 100644 --- a/numba/core/utils.py +++ b/numba/core/utils.py @@ -12,6 +12,7 @@ import weakref import warnings from types import ModuleType +from importlib import import_module from collections.abc import Mapping import numpy as np @@ -555,3 +556,38 @@ def unified_function_type(numba_types, require_precise=True): function = types.UndefinedFunctionType(mnargs, dispatchers) return function + + +class _RedirectSubpackage(ModuleType): + """Redirect a subpackage to a subpackage. + + This allows all references like: + + >>> from numba.old_subpackage import module + >>> module.item + + >>> import numba.old_subpackage.module + >>> numba.old_subpackage.module.item + + >>> from numba.old_subpackage.module import item + """ + def __init__(self, old_module_locals, new_module): + old_module = old_module_locals['__name__'] + super().__init__(old_module) + + new_mod_obj = import_module(new_module) + + # Map all sub-modules over + for k, v in new_mod_obj.__dict__.items(): + # Get attributes so that `subpackage.xyz` and + # `from subpackage import xyz` work + setattr(self, k, v) + if isinstance(v, ModuleType): + # Map modules into the interpreter so that + # `import subpackage.xyz` works + sys.modules[f"{old_module}.{k}"] = sys.modules[v.__name__] + + # copy across dunders so that package imports work too + for attr, value in old_module_locals.items(): + if attr.startswith('__') and attr.endswith('__'): + setattr(self, attr, value) diff --git a/numba/tests/test_moved_modules.py b/numba/tests/test_moved_modules.py index 81e61a2f108..4ccaa06c9a4 100644 --- a/numba/tests/test_moved_modules.py +++ b/numba/tests/test_moved_modules.py @@ -9,8 +9,8 @@ class TestMovedModule(TestCase): def tests_numba_types(self): import numba.types import numba.core.types as types - # The old module is the new module - self.assertIs(numba.types, types) + # The old module IS NOT the new module + self.assertIsNot(numba.types, types) # Attribute access are there self.assertIs(numba.types.intp, types.intp) self.assertIs(numba.types.float64, types.float64) @@ -19,3 +19,12 @@ def tests_numba_types(self): import numba.types.misc self.assertIs(types.misc, numba.types.misc) self.assertIs(types.misc.Optional, numba.types.misc.Optional) + # Import time code could be executed twice and causes the following to + # fail. + self.assertIs(types.StringLiteral, numba.types.misc.StringLiteral) + # Check numba.types.container + from numba.types import containers + self.assertIs(types.containers, containers) + self.assertIs(types.containers.Sequence, containers.Sequence) + from numba.types.containers import Sequence + self.assertIs(Sequence, containers.Sequence) diff --git a/numba/types/__init__.py b/numba/types/__init__.py index cab9204c75c..3bb9f219803 100644 --- a/numba/types/__init__.py +++ b/numba/types/__init__.py @@ -1,3 +1,4 @@ import sys -import numba.core.types -sys.modules[__name__] = numba.core.types +from numba.core.utils import _RedirectSubpackage +sys.modules[__name__] = _RedirectSubpackage(locals(), "numba.core.types") +