Skip to content
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

Fix crash in ExplicitNamespacePackageFinder #1714

Merged

Conversation

jacobtylerwalls
Copy link
Member

@jacobtylerwalls jacobtylerwalls commented Jul 16, 2022

Steps

  • For new features or bug fixes, add a ChangeLog entry describing what your PR does.
  • Write a good description on what the PR does.

Description

Some weirdness with _SixMetaPathImporter demonstrated that astroid.interpreter._import.util.is_namespace needs to check the presence of submodule_search_locations before reporting something to be a namespace package.

Type of Changes

Type
🐛 Bug fix

Related Issue

Closes #1708

@coveralls
Copy link

coveralls commented Jul 16, 2022

Pull Request Test Coverage Report for Build 2769984269

  • 1 of 1 (100.0%) changed or added relevant line in 1 file are covered.
  • No unchanged relevant lines lost coverage.
  • Overall coverage decreased (-0.001%) to 92.256%

Totals Coverage Status
Change from base Build 2724794959: -0.001%
Covered Lines: 9697
Relevant Lines: 10511

💛 - Coveralls

@jacobtylerwalls jacobtylerwalls marked this pull request as draft July 16, 2022 14:19
Copy link
Member

@Pierre-Sassoulas Pierre-Sassoulas left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM !

@@ -201,7 +201,12 @@ def find_module(
if processed:
modname = ".".join(processed + [modname])
if util.is_namespace(modname) and modname in sys.modules:
submodule_path = sys.modules[modname].__path__
try:
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we understand why __path__ isn't available?

https://docs.python.org/3/reference/import.html#path__
If the module is a package (either regular or namespace), the module object’s __path__ attribute must be set.

We probably shouldn't crash, but is this "normal" behaviour?

https://docs.python.org/3/library/importlib.html#importlib.machinery.ModuleSpec
Thus it is possible to update the module’s __path__ at runtime, and this will not be automatically reflected in __spec__.submodule_search_locations.

__path__ not being available seems to indicate that this isn't a package and thus perhaps we shouldn't return a ModuleSpec with a PY_NAMESPACE type?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just dashing off a quick reply that when I looked into it I thought it was because urllib3 was doing magic with six, so I wasn't concerned, but I can try to get a real answer :-)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Coming back to this, I guess I don't want to take on the burden of understanding _SixMetaPathImporter inside and out -- there are four bugs filed against it anyway, so I wouldn't trust it to work in all scenarios, esp. if libraries like urllib3 are doing things on top of it. I'd rather just catch the error until someone can demonstrate that astroid is at fault.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sometime the code is too dynamic to be reasonably understood by astroid. Understanding this kind of dynamic code would be very good and reduce the use of brain and workarounds but I agree with @jacobtylerwalls. Ready to release the next patch version of astroid as soon as we merge this :)

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note that this is still on my radar but I haven't been around much. Should be able to get to this in a 10 days or so. My main question is whether the check for __path__ should be included in the is_namespace function.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks Daniel, looking again, I think you have a point. I pushed a new commit to fix this in is_namespace(). ModuleSpec has submodule_search_locations as a better name than __path__ per PEP 451.

@Pierre-Sassoulas
Copy link
Member

It looks pretty similar to an issue we have with pypy in pylint's main https://github.com/PyCQA/pylint/runs/7428964268?check_suite_focus=true

Pierre-Sassoulas added a commit to Pierre-Sassoulas/pylint that referenced this pull request Jul 30, 2022
Pierre-Sassoulas added a commit to Pierre-Sassoulas/pylint that referenced this pull request Jul 30, 2022
Pierre-Sassoulas added a commit to pylint-dev/pylint that referenced this pull request Jul 30, 2022
@pytest.mark.skipif(not HAS_URLLIB3, reason="This test requires urllib3.")
def test_file_info_from_modpath__SixMetaPathImporter() -> None:
pytest.raises(
ImportError,
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So we no longer have a finder that will find the module created by _SixMetaPathImporter, but that's better than crashing while trying to find it with ExplicitNamespacePackageFinder (or incorrectly finding it with it!)

@jacobtylerwalls jacobtylerwalls added the pylint-tested PRs that don't cause major regressions with pylint label Jul 31, 2022
Copy link
Member

@Pierre-Sassoulas Pierre-Sassoulas left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

ChangeLog Outdated Show resolved Hide resolved

return found_spec.origin is None
return (
found_spec is not None
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we use last_submodule_search_locations here?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't know, I suspect (without looking too closely) that could create false positives if a portion of the path was a valid namespace package but the rest of the path wasn't. That variable is really just a hack to get around the KeyError described in the comment, I wouldn't trust it to represent more than that.

@Pierre-Sassoulas Pierre-Sassoulas merged commit 93ca875 into pylint-dev:main Aug 9, 2022
@Pierre-Sassoulas
Copy link
Member

I won't be able to release astroid until Friday, feel free to release if you want @jacobtylerwalls :)

@potiuk
Copy link

potiuk commented Aug 9, 2022

Cool. Looking forward to it :)

@jacobtylerwalls jacobtylerwalls deleted the namespace-path-crash branch August 9, 2022 11:01
DanielNoord pushed a commit to DanielNoord/astroid that referenced this pull request Aug 23, 2022
* Add skip if no `six`
* `urllib3` does appear to be required
* Check `submodule_search_locations`

Co-authored-by: Pierre Sassoulas <pierre.sassoulas@gmail.com>
DanielNoord pushed a commit that referenced this pull request Aug 23, 2022
* Add skip if no `six`
* `urllib3` does appear to be required
* Check `submodule_search_locations`

Co-authored-by: Pierre Sassoulas <pierre.sassoulas@gmail.com>
@DanielNoord DanielNoord mentioned this pull request Aug 23, 2022
2 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Crash 💥 pylint-tested PRs that don't cause major regressions with pylint
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Astroid 2.12 breaks sphinx autoapi (at least for Airflow)
5 participants