Skip to content

Refactor import diagnostics, fix diagnostics in some fine-grained cases #4840

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

Merged
merged 4 commits into from
Apr 3, 2018

Conversation

msullivan
Copy link
Collaborator

Refactor all of the import diagnostics so that they can be used
outside of State's __init__ method.

Then use that to fix some problems with import diagnostics in fine-grained mode.
Fixes #4798.

This refactor also lays the ground work for fixing (coarse) incremental mode's interaction
with --warn-unused-ignores

Copy link
Collaborator

@JukkaL JukkaL left a comment

Choose a reason for hiding this comment

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

Thanks for cleaning this up! Looks good, just left some minor comments.

mypy/build.py Outdated
root_source: bool = False) -> Tuple[str, str]:
"""Find a module by name, respecting follow_imports and producing diagnostics.

"""
Copy link
Collaborator

Choose a reason for hiding this comment

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

Document the return value and arguments.

mypy/build.py Outdated

def skipping_module(manager: BuildManager, line: int, caller_state: Optional[State],
id: str, path: str) -> None:
assert caller_state, (id, path)
Copy link
Collaborator

Choose a reason for hiding this comment

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

Add short docstring (no need to explain arguments in detail)?

mypy/build.py Outdated


def skipping_ancestor(manager: BuildManager, id: str, path: str, ancestor_for: 'State') -> None:
# TODO: Read the path (the __init__.py file) and return
Copy link
Collaborator

Choose a reason for hiding this comment

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

Add short docstring (no need to explain arguments in detail)?

mypy/build.py Outdated
manager, self.options, dep,
caller_state=state, caller_line=line,
ancestor_for=ancestor)
except Exception:
Copy link
Collaborator

Choose a reason for hiding this comment

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

A catch-all except looks a bit suspicious. Would it be possible to explicitly enumerate the exceptions that we are expecting here? Some exceptions such as TypeErrors we probably don't want to silently ignore.

[file a.py]
import b
from c import x
[file b.py]
Copy link
Collaborator

Choose a reason for hiding this comment

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

Maybe include something here that would trigger an error to verify that this actually gets skipped? Maybe also update b.py?

[file a.py]
from c import x
import b
[file b.py]
Copy link
Collaborator

Choose a reason for hiding this comment

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

Again maybe introduce an error here that shouldn't be reported?

a.py:2: note: Import of 'b' ignored
a.py:2: note: (Using --follow-imports=error, module not passed on command line)

-- This test fails because p.b doesn't seem to trigger p properly...
Copy link
Collaborator

Choose a reason for hiding this comment

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

Create an issue about this (if one doesn't already exist) and mention it here.

Copy link
Member

@gvanrossum gvanrossum left a comment

Choose a reason for hiding this comment

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

Here are some more comments.

mypy/build.py Outdated
@@ -2008,6 +1909,34 @@ def write_cache(self) -> None:
self.mark_interface_stale()
self.interface_hash = new_interface_hash

def verify_dependencies(self) -> None:
"""Report errors for import targets in module that don't exist."""
Copy link
Member

Choose a reason for hiding this comment

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

s/module/modules/

mypy/build.py Outdated
@@ -2018,6 +1947,132 @@ def generate_unused_ignore_notes(self) -> None:
if self.options.warn_unused_ignores:
self.manager.errors.generate_unused_ignore_notes(self.xpath)

# Module import and diagnostic glue
Copy link
Member

Choose a reason for hiding this comment

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

Move one line down.

mypy/build.py Outdated
root_source: bool = False) -> Tuple[str, str]:
"""Find a module by name, respecting follow_imports and producing diagnostics.

"""
Copy link
Member

Choose a reason for hiding this comment

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

Shorten docstring.

mypy/build.py Outdated
if self.priorities.get(dep) != PRI_INDIRECT]
assert self.ancestors is not None
for dep in dependencies + self.suppressed + self.ancestors:
if dep not in manager.modules and not manager.options.ignore_missing_imports:
Copy link
Member

Choose a reason for hiding this comment

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

Hm, ignore_missing_imports is a per-module option. Can you use graph[dep].options.ignore_missing_imports? (Though you may have to figure out how to pass the graph here.) I don't think that self.options is quite right (since it indicates whether self.id should be ignored if not found, not modules it depends on) but I'm not 100% sure.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Good catch.

graph[dep].options won't be the right thing, since the whole problem here is that the module isn't in graph, which is why we are considering reporting an error. I think the right thing is manager.options.clone_for_module(dep).

mypy/build.py Outdated
"(Using --follow-imports=error, submodule passed on command line)",
severity='note', only_once=True)

# The driver
Copy link
Member

Choose a reason for hiding this comment

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

Move down a line.

mypy/build.py Outdated
# - skip -> don't analyze, make the type Any
follow_imports = options.follow_imports
if (root_source # Honor top-level modules
or not (path.endswith('.py') # Stubs are always normal
Copy link
Member

Choose a reason for hiding this comment

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

Indent this and the next line 4 more. Also, maybe "or not (X or Y)" is more clearly written as "or (not X and not Y)"? Seeing 'not' twice feels less offensive than having to decipher "or not or".

@msullivan msullivan merged commit db02926 into master Apr 3, 2018
@msullivan msullivan deleted the module-loading branch April 4, 2018 00:06
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Fine-grained mode doesn't properly respect --follow-imports settings when producing error messages
3 participants