New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
bpo-45379: raise import error on FROZEN_BAD_NAME #29180
base: main
Are you sure you want to change the base?
Conversation
Note that the existing behavior has been around for a long time. So we need to be sure this change won't break people. |
Yes, I understand. How do you propose doing that? |
I did some detective work, it seems almost nobody uses this function, which is not really unexpected |
FWIW, I agree that this change in behavior is extremely unlikely to break anyone. The users of As to the severity of hitting the error, it will be clear what the problem is and how to fix it. Callers would have to add code to treat the exception as "not found" if they prefer the existing behavior but I expect they would rather have the exception (to distinguish from "not found"). I suppose it might be worth adding a paragraph to the "Porting to Python 3.11" section of Doc/whatsnew/3.11.rst, just in case. |
Sorry for the delay, @FFY00! Thanks for working on this.
_imp_find_frozen_impl()
should also be updated in the same way. When you do that, FrozenImporter.find_spec()
needs to be updated to return None
if it hits that ImportError
. Otherwise it will cause import to fail instead of trying the next finder on sys.metapath
. It would probably make sense to emit a warning in that case. (@brettcannon, what do you think?)
In find_frozen()
, we call PyErr_Clear()
when emitting FROZEN_BAD_NAME
. (There's a long comment there about why.) Now that we're always raising ImportError
, it would be helpful to users if we preserve (chain) the error here instead of clearing it.
Also, please add a test for this exception case, both for PyImport_ImportFrozenModuleObject()
(via _test_embed
) and _imp.find_frozen()
. Clearly this case isn't tested or your change would have caused the existing test to fail.
Other than that I just have a couple comments about explicitly noting the change in behavior.
Misc/NEWS.d/next/Core and Builtins/2021-10-23-00-55-22.bpo-45379.ShZAZ7.rst
Outdated
Show resolved
Hide resolved
A Python core developer has requested some changes be made to your pull request before we can consider merging it. If you could please address their requests along with any other requests in other reviews from core developers that would be appreciated. Once you have made the requested changes, please leave a comment on this pull request containing the phrase And if you don't make the requested changes, you will be put in the comfy chair! |
cpython/Python/clinic/import.c.h Line 193 in aae18a1
Python 3.11.0a1+ (heads/[bpo-45379](https://bugs.python.org/issue45379)-bad-name:e225f44088, Oct 30 2021, 19:47:09) [GCC 11.1.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import _imp
>>> _imp.find_frozen(None)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: find_frozen() argument 1 must be str, not None Considering this, does |
Nevermind, this can indeed be triggered if we don't get valid unicode. $ ./python -c "__import__('\\udcff')"
Traceback (most recent call last):
File "<string>", line 1, in <module>
ImportError: Invalid frozen object name ('\udcff') |
``` >>> from ctypes import py_object, pythonapi as capi >>> capi.PyImport_ImportFrozenModuleObject(py_object(None)) Traceback (most recent call last): File "<stdin>", line 1, in <module> ImportError: Invalid frozen object name (None) ``` Signed-off-by: Filipe Laíns <[email protected]>
Co-authored-by: Eric Snow <[email protected]> Signed-off-by: Filipe Laíns <[email protected]>
Signed-off-by: Filipe Laíns <[email protected]>
Signed-off-by: Filipe Laíns <[email protected]>
Signed-off-by: Filipe Laíns <[email protected]>
Signed-off-by: Filipe Laíns <[email protected]>
Signed-off-by: Filipe Laíns <[email protected]>
Signed-off-by: Filipe Laíns <[email protected]>
Thanks again for working on this. It mostly LGTM. There are just a few minor things to address before we merge this.
@@ -1202,11 +1204,13 @@ set_frozen_error(frozen_status status, PyObject *modname) | |||
Py_UNREACHABLE(); | |||
} | |||
if (err != NULL) { | |||
PyObject *type, *value, *traceback; | |||
PyErr_Fetch(&type, &value, &traceback); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We want to chain the exception. So do one of the following:
- drop this line (AFAICS,
PyErr_SetImportError()
chains the exception if one is set) - call
_PyErr_ChainExceptions(type, value, traceback)
after thePyErr_SetImportError()
call (line 1213)
{"test_import_frozen_module_null", test_import_frozen_module_null}, | ||
{"test_import_frozen_module_none", test_import_frozen_module_none}, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There need to be corresponding tests in Lib/test/test_embed.py.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually, wouldn't the relevant code be more appropriate in Modules/_testcapimodule.c
and the tests in Lib/test/test_capi.py (or even Lib/test/test_import/init.py)? As a bonus, you wouldn't need to do so much in the C code that way.
try: | ||
info = _call_with_frames_removed(_imp.find_frozen, fullname) | ||
except ImportError: | ||
return None |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Users may find it helpful if we also emitted a warning here.
@@ -2146,7 +2147,8 @@ _imp_find_frozen_impl(PyObject *module, PyObject *name, int withdata) | |||
Py_RETURN_NONE; | |||
} | |||
else if (status == FROZEN_BAD_NAME) { | |||
Py_RETURN_NONE; | |||
set_frozen_error(status, name); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should have a test in Lib/test/test_imp.py. We should also have one in one in Lib/test/test_importlib/frozen/test_finder.py, to verify FrozenImporter.find_spec()
returns None in that case.
Thank you for reviewing, I will go over this and rebase later. |
Sorry for the long delay! |
Signed-off-by: Filipe Laíns [email protected]
https://bugs.python.org/issue45379