diff --git a/Lib/importlib/_bootstrap.py b/Lib/importlib/_bootstrap.py --- a/Lib/importlib/_bootstrap.py +++ b/Lib/importlib/_bootstrap.py @@ -998,16 +998,20 @@ def _handle_fromlist(module, fromlist, i # If a package was imported, try to import stuff from fromlist. if hasattr(module, '__path__'): if '*' in fromlist: fromlist = list(fromlist) fromlist.remove('*') if hasattr(module, '__all__'): fromlist.extend(module.__all__) for x in fromlist: + if not isinstance(x, str): + raise TypeError( + f"Item in 'from list' must be str, not {type(x).__name__!r}" + ) if not hasattr(module, x): from_name = '{}.{}'.format(module.__name__, x) try: _call_with_frames_removed(import_, from_name) except ModuleNotFoundError as exc: # Backwards-compatibility dictates we ignore failed # imports triggered by fromlist for modules that don't # exist. diff --git a/Lib/test/test_importlib/import_/test_api.py b/Lib/test/test_importlib/import_/test_api.py --- a/Lib/test/test_importlib/import_/test_api.py +++ b/Lib/test/test_importlib/import_/test_api.py @@ -77,16 +77,23 @@ class APITest: mod.__path__ = ['XXX'] with util.import_state(meta_path=[self.bad_finder_loader]): with util.uncache(PKG_NAME): sys.modules[PKG_NAME] = mod with self.assertRaises(ImportError): self.__import__(PKG_NAME, fromlist=[SUBMOD_NAME.rpartition('.')[-1]]) + def test_fromlist_invalid_type(self): + with self.assertRaises(TypeError) as cm: + self.__import__('encodings', fromlist=[b'aliases']) + self.assertEqual( + str(cm.exception), "Item in 'from list' must be str, not 'bytes'" + ) + class OldAPITests(APITest): bad_finder_loader = BadLoaderFinder (Frozen_OldAPITests, Source_OldAPITests ) = util.test_both(OldAPITests, __import__=util.__import__)