https://github.com/python/cpython/commit/6441d42f92f9daa2f3d9ff0ec3de0d60c26e041d
commit: 6441d42f92f9daa2f3d9ff0ec3de0d60c26e041d
branch: 3.13
author: Shantanu <[email protected]>
committer: hauntsaninja <[email protected]>
date: 2024-12-10T05:21:55Z
summary:

[3.13] gh-127651: Use __file__ in diagnostics if origin is missing (#127660) 
(#127775)

gh-127651: Use __file__ in diagnostics if origin is missing (#127660)

See the left hand side in 
https://github.com/python/cpython/pull/123929/files#diff-c22186367cbe20233e843261998dc027ae5f1f8c0d2e778abfa454ae74cc59deL2840-L2849

---------

Co-authored-by: Serhiy Storchaka <[email protected]>
(cherry picked from commit 3983527c3a6b389e373a233e514919555853ccb3)

files:
A Misc/NEWS.d/next/Core and 
Builtins/2024-12-06-01-09-40.gh-issue-127651.80cm6j.rst
M Lib/test/test_import/__init__.py
M Python/ceval.c

diff --git a/Lib/test/test_import/__init__.py b/Lib/test/test_import/__init__.py
index 9139d455f4a16d..58c6aaf0986bcf 100644
--- a/Lib/test/test_import/__init__.py
+++ b/Lib/test/test_import/__init__.py
@@ -826,6 +826,50 @@ def test_issue105979(self):
         self.assertIn("Frozen object named 'x' is invalid",
                       str(cm.exception))
 
+    def test_frozen_module_from_import_error(self):
+        with self.assertRaises(ImportError) as cm:
+            from os import this_will_never_exist
+        self.assertIn(
+            f"cannot import name 'this_will_never_exist' from 'os' 
({os.__file__})",
+            str(cm.exception),
+        )
+        with self.assertRaises(ImportError) as cm:
+            from sys import this_will_never_exist
+        self.assertIn(
+            "cannot import name 'this_will_never_exist' from 'sys' (unknown 
location)",
+            str(cm.exception),
+        )
+
+        scripts = [
+            """
+import os
+os.__spec__.has_location = False
+os.__file__ = []
+from os import this_will_never_exist
+""",
+            """
+import os
+os.__spec__.has_location = False
+del os.__file__
+from os import this_will_never_exist
+""",
+              """
+import os
+os.__spec__.origin = []
+os.__file__ = []
+from os import this_will_never_exist
+"""
+        ]
+        for script in scripts:
+            with self.subTest(script=script):
+                expected_error = (
+                    b"cannot import name 'this_will_never_exist' "
+                    b"from 'os' (unknown location)"
+                )
+                popen = script_helper.spawn_python("-c", script)
+                stdout, stderr = popen.communicate()
+                self.assertIn(expected_error, stdout)
+
     def test_script_shadowing_stdlib(self):
         script_errors = [
             (
@@ -1087,7 +1131,7 @@ class substr(str):
 except AttributeError as e:
     print(str(e))
 
-fractions.__spec__.origin = 0
+fractions.__spec__.origin = []
 try:
     fractions.Fraction
 except AttributeError as e:
@@ -1111,7 +1155,7 @@ class substr(str):
 except ImportError as e:
     print(str(e))
 
-fractions.__spec__.origin = 0
+fractions.__spec__.origin = []
 try:
     from fractions import Fraction
 except ImportError as e:
diff --git a/Misc/NEWS.d/next/Core and 
Builtins/2024-12-06-01-09-40.gh-issue-127651.80cm6j.rst b/Misc/NEWS.d/next/Core 
and Builtins/2024-12-06-01-09-40.gh-issue-127651.80cm6j.rst
new file mode 100644
index 00000000000000..92b18b082eb30e
--- /dev/null
+++ b/Misc/NEWS.d/next/Core and 
Builtins/2024-12-06-01-09-40.gh-issue-127651.80cm6j.rst 
@@ -0,0 +1 @@
+When raising :exc:`ImportError` for missing symbols in ``from`` imports, use 
``__file__`` in the error message if ``__spec__.origin`` is not a location
diff --git a/Python/ceval.c b/Python/ceval.c
index d970ffa0309a8d..c502a5398a0375 100644
--- a/Python/ceval.c
+++ b/Python/ceval.c
@@ -2785,6 +2785,20 @@ import_from(PyThreadState *tstate, PyObject *v, PyObject 
*name)
         }
     }
 
+    if (origin == NULL) {
+        // Fall back to __file__ for diagnostics if we don't have
+        // an origin that is a location
+        origin = PyModule_GetFilenameObject(v);
+        if (origin == NULL) {
+            if (!PyErr_ExceptionMatches(PyExc_SystemError)) {
+                goto done;
+            }
+            // PyModule_GetFilenameObject raised "module filename missing"
+            _PyErr_Clear(tstate);
+        }
+        assert(origin == NULL || PyUnicode_Check(origin));
+    }
+
     if (is_possibly_shadowing_stdlib) {
         assert(origin);
         errmsg = PyUnicode_FromFormat(
@@ -2845,9 +2859,11 @@ import_from(PyThreadState *tstate, PyObject *v, PyObject 
*name)
     }
 
 done_with_errmsg:
-    /* NULL checks for errmsg, mod_name, origin done by PyErr_SetImportError. 
*/
-    _PyErr_SetImportErrorWithNameFrom(errmsg, mod_name, origin, name);
-    Py_DECREF(errmsg);
+    if (errmsg != NULL) {
+        /* NULL checks for mod_name and origin done by 
_PyErr_SetImportErrorWithNameFrom */
+        _PyErr_SetImportErrorWithNameFrom(errmsg, mod_name, origin, name);
+        Py_DECREF(errmsg);
+    }
 
 done:
     Py_XDECREF(origin);

_______________________________________________
Python-checkins mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3/lists/python-checkins.python.org/
Member address: [email protected]

Reply via email to