-
-
Notifications
You must be signed in to change notification settings - Fork 31.7k
gh-122353: Handle ValueError
during imports
#122389
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
base: main
Are you sure you want to change the base?
Conversation
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.
Thank you. I have only two more comments.
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.
The patch is good overall, but I want to be more fully convinced that (a) users shouldn't be told when they provide bad values, or (b) we shouldn't be raising OSError from the path converter instead. Discussion on #122353 please.
Doc/library/importlib.rst
Outdated
If the *path* cannot be handled, this raises an :exc:`OSError` | ||
or a :exc:`ValueError` depending on the reason. |
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 deliberately don't document ValueError
in most cases because it's assumed to be a possibility whenever you pass in an invalid value. If we start documenting it, we'll end up having to put it on every single function.
I'd rather skip all these doc changes and keep with our usual conventions. It may be surprising at first, but the error does only occur when an invalid value is provided, and not due to OS/environment issues (which are the cause of the OSError, and we document functions that may do something that could result in an OSError because most do not).
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.
Since OSError is already explicitly documented here, I do not see harm in mentioning also ValueError which depends on OS and environment. For example, UnicodeEncodeError (which is a subclass of ValueError) can be raised depending on the locale.
This is also important for end user to know which exceptions they should catch. OSError and ValueError are not raised in normal cases, but they can be raised depending on user data, OS and environment. It is easy to miss ValueError.
Such exceptions like TypeError, MemoryError, RecursionError should not be explicitly documented.
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.
It depends on the OS, but not on the state of the OS (what I meant by "environment", as opposed to "environment variables" which are only one aspect of the overall state).
ValueError can be raised practically anywhere. If you aren't sure you're passing a valid value, you always need to handle ValueError. It's in the same category as TypeError, MemoryError and RecursionError (and AttributeError when calling a function, as this is essentially the same as TypeError).
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.
Another phrasing issue here is the switch from the imperative "is to be raised" to the descriptive "this raises". It's an abstract method definition giving instructions to subclass authors, so the "is to be raised" phrasing should be kept.
Due to that, I do think it's reasonable to mention ValueError
explicitly here, specifically so subclass method implementors don't feel obliged to catch it and turn it into OSError
.
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 |
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.
LGTM.
Doc/library/importlib.rst
Outdated
If the *path* cannot be handled, this raises an :exc:`OSError` | ||
or a :exc:`ValueError` depending on the reason. |
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.
Since OSError is already explicitly documented here, I do not see harm in mentioning also ValueError which depends on OS and environment. For example, UnicodeEncodeError (which is a subclass of ValueError) can be raised depending on the locale.
This is also important for end user to know which exceptions they should catch. OSError and ValueError are not raised in normal cases, but they can be raised depending on user data, OS and environment. It is easy to miss ValueError.
Such exceptions like TypeError, MemoryError, RecursionError should not be explicitly documented.
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.
The test case update looks good to me, but several requests and suggestions inline for the details of the docs and implementation changes.
Doc/library/importlib.rst
Outdated
If the *path* cannot be handled, this raises an :exc:`OSError` | ||
or a :exc:`ValueError` depending on the reason. |
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.
Another phrasing issue here is the switch from the imperative "is to be raised" to the descriptive "this raises". It's an abstract method definition giving instructions to subclass authors, so the "is to be raised" phrasing should be kept.
Due to that, I do think it's reasonable to mention ValueError
explicitly here, specifically so subclass method implementors don't feel obliged to catch it and turn it into OSError
.
If the *path* cannot be handled, this raises an :exc:`OSError` | ||
or a :exc:`ValueError` depending on the reason. |
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.
Exceptions are covered in ResourceLoader abstract method documentation above.
If the *path* cannot be handled, this raises an :exc:`OSError` | |
or a :exc:`ValueError` depending on the reason. |
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, I duplicated the entry because the ABC marked as deprecated since 3.7. As such, I'm not sure whether the ABC should update its documentation or not...
Doc/library/importlib.rst
Outdated
When writing to the path fails by raising an :class:`OSError` | ||
or a :class:`ValueError`, the exception is not propagated. |
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 change is not correct, only a lack of write permissions should be silently ignored, everything else should be propagated (despite importlib
itself being overly broad in the errors it suppresses).
When writing to the path fails by raising an :class:`OSError` | |
or a :class:`ValueError`, the exception is not propagated. | |
When writing to the path fails because the path is read-only | |
(:const:`errno.EACCES`/:exc:`PermissionError`), do not propagate the | |
exception. Other exceptions should still be propagated. |
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.
Since the tests are failing, should we also protect against FileExistsError
when writing the data? By suppressing OSError altogether, we actually suppressed FileExistsError
in free-threaded builds and read-only errors (those with errno 30 but that are not explicitly PermissionError).
It seems that the FileExistsError
only happens in free-threaded builds of Mac OS but I'm not sure whether it's related or not...
Lib/importlib/_bootstrap_external.py
Outdated
except OSError as exc: | ||
# Could be a permission error, read-only filesystem: just forget | ||
# about writing the data. | ||
except (OSError, ValueError) as exc: |
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 be made narrower rather than broader (i.e. only ignoring PermissionError
)
Lib/importlib/_bootstrap_external.py
Outdated
_bootstrap._verbose_message('could not create {!r}: {!r}', | ||
parent, exc) | ||
return | ||
try: | ||
_write_atomic(path, data, _mode) | ||
_bootstrap._verbose_message('created {!r}', path) | ||
except OSError as exc: | ||
except (OSError, ValueError) as exc: |
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.
Ditto on the narrower catch.
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 |
There is a pending doc question I have but otherwise it should be good for a second round of reviews (btw, thank you all for your time). I have made the requested changes; please review again. |
Thanks for making the requested changes! @serhiy-storchaka, @zooba, @ncoghlan: please review the changes made to this pull request. |
…thon into handle-valueerror-on-imports
@ncoghlan Could you have a look at the modified text and the question I had please (#122389 (comment))? Thank you! @zooba Could you confirm whether the latest changes are fine? Thank you! |
This is a simple fix but I am not an expert enough concerning the import system. The idea is to also catch the ValueError that could be raised by any function using the
path_t
AC converter (or by any other handler that is explicitly raising it).