diff options
author | Matthias Bussonnier <bussonniermatthias@gmail.com> | 2017-02-15 00:05:25 (GMT) |
---|---|---|
committer | Brett Cannon <brettcannon@users.noreply.github.com> | 2017-02-15 00:05:25 (GMT) |
commit | bc4bed440504597cac47d0a215ee094bfa99ba7e (patch) | |
tree | 0598b2b4776f859b7ab15f70e7cdb65475c5d8c1 | |
parent | 5ec08cea9574cf53c985af5dbed6bc3d56ff58b7 (diff) | |
download | cpython-bc4bed440504597cac47d0a215ee094bfa99ba7e.zip cpython-bc4bed440504597cac47d0a215ee094bfa99ba7e.tar.gz cpython-bc4bed440504597cac47d0a215ee094bfa99ba7e.tar.bz2 |
bpo-29546: Set 'path' on ImportError for ``from ... import ...`` (GH-91)
-rw-r--r-- | Lib/test/test_import/__init__.py | 19 | ||||
-rw-r--r-- | Misc/NEWS | 2 | ||||
-rw-r--r-- | Python/ceval.c | 12 |
3 files changed, 31 insertions, 2 deletions
diff --git a/Lib/test/test_import/__init__.py b/Lib/test/test_import/__init__.py index d61782a..df678f1 100644 --- a/Lib/test/test_import/__init__.py +++ b/Lib/test/test_import/__init__.py @@ -80,6 +80,25 @@ class ImportTests(unittest.TestCase): with self.assertRaises(ImportError): from importlib import something_that_should_not_exist_anywhere + def test_from_import_missing_attr_has_name_and_path(self): + with self.assertRaises(ImportError) as cm: + from os import i_dont_exist + self.assertEqual(cm.exception.name, 'os') + self.assertEqual(cm.exception.path, os.__file__) + + def test_from_import_missing_attr_has_name(self): + with self.assertRaises(ImportError) as cm: + # _warning has no path as it's a built-in module. + from _warning import i_dont_exist + self.assertEqual(cm.exception.name, '_warning') + self.assertIsNone(cm.exception.path) + + def test_from_import_missing_attr_path_is_canonical(self): + with self.assertRaises(ImportError) as cm: + from os.path import i_dont_exist + self.assertIn(cm.exception.name, {'posixpath', 'ntpath'}) + self.assertIsNotNone(cm.exception) + def test_case_sensitivity(self): # Brief digression to test that import is case-sensitive: if we got # this far, we know for sure that "random" exists. @@ -12,6 +12,8 @@ Core and Builtins - bpo-29438: Fixed use-after-free problem in key sharing dict. +- bpo-29546: Set the 'path' and 'name' attribute on ImportError for ``from ... import ...``. + - Issue #29319: Prevent RunMainFromImporter overwriting sys.path[0]. - Issue #29337: Fixed possible BytesWarning when compare the code objects. diff --git a/Python/ceval.c b/Python/ceval.c index 66fd361..69c9383 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -4995,7 +4995,7 @@ import_from(PyObject *v, PyObject *name) { PyObject *x; _Py_IDENTIFIER(__name__); - PyObject *fullmodname, *pkgname; + PyObject *fullmodname, *pkgname, *pkgpath; x = PyObject_GetAttr(v, name); if (x != NULL || !PyErr_ExceptionMatches(PyExc_AttributeError)) @@ -5021,7 +5021,15 @@ import_from(PyObject *v, PyObject *name) Py_INCREF(x); return x; error: - PyErr_Format(PyExc_ImportError, "cannot import name %R", name); + pkgpath = PyModule_GetFilenameObject(v); + + if (pkgpath == NULL || !PyUnicode_Check(pkgpath)) { + PyErr_Clear(); + PyErr_SetImportError(PyUnicode_FromFormat("cannot import name %R", name), pkgname, NULL); + } else { + PyErr_SetImportError(PyUnicode_FromFormat("cannot import name %R", name), pkgname, pkgpath); + } + return NULL; } |