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 dmypy inspect for namespace packages #16357

Merged
merged 2 commits into from
Oct 30, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
4 changes: 3 additions & 1 deletion mypy/dmypy_server.py
Original file line number Diff line number Diff line change
Expand Up @@ -461,6 +461,7 @@ def initialize_fine_grained(
messages = result.errors
self.fine_grained_manager = FineGrainedBuildManager(result)

original_sources_len = len(sources)
if self.following_imports():
sources = find_all_sources_in_build(self.fine_grained_manager.graph, sources)
self.update_sources(sources)
Expand Down Expand Up @@ -525,7 +526,8 @@ def initialize_fine_grained(

__, n_notes, __ = count_stats(messages)
status = 1 if messages and n_notes < len(messages) else 0
messages = self.pretty_messages(messages, len(sources), is_tty, terminal_width)
# We use explicit sources length to match the logic in non-incremental mode.
messages = self.pretty_messages(messages, original_sources_len, is_tty, terminal_width)
return {"out": "".join(s + "\n" for s in messages), "err": "", "status": status}

def fine_grained_increment(
Expand Down
16 changes: 5 additions & 11 deletions mypy/inspections.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
from typing import Callable

from mypy.build import State
from mypy.find_sources import InvalidSourceList, SourceFinder
from mypy.messages import format_type
from mypy.modulefinder import PYTHON_EXTENSIONS
from mypy.nodes import (
Expand Down Expand Up @@ -206,9 +205,6 @@ def __init__(
force_reload: bool = False,
) -> None:
self.fg_manager = fg_manager
self.finder = SourceFinder(
self.fg_manager.manager.fscache, self.fg_manager.manager.options
)
self.verbosity = verbosity
self.limit = limit
self.include_span = include_span
Expand Down Expand Up @@ -561,16 +557,14 @@ def find_module(self, file: str) -> tuple[State | None, dict[str, object]]:
if not any(file.endswith(ext) for ext in PYTHON_EXTENSIONS):
return None, {"error": "Source file is not a Python file"}

try:
module, _ = self.finder.crawl_up(os.path.normpath(file))
except InvalidSourceList:
return None, {"error": "Invalid source file name: " + file}

state = self.fg_manager.graph.get(module)
# We are using a bit slower but robust way to find a module by path,
# to be sure that namespace packages are handled properly.
abs_path = os.path.abspath(file)
state = next((s for s in self.fg_manager.graph.values() if s.abspath == abs_path), None)
self.module = state
return (
state,
{"out": f"Unknown module: {module}", "err": "", "status": 1} if state is None else {},
{"out": f"Unknown module: {file}", "err": "", "status": 1} if state is None else {},
)

def run_inspection(
Expand Down
2 changes: 1 addition & 1 deletion mypy/test/testfinegrained.py
Original file line number Diff line number Diff line change
Expand Up @@ -352,7 +352,7 @@ def maybe_inspect(self, step: int, server: Server, src: str) -> list[str]:
)
val = res["error"] if "error" in res else res["out"] + res["err"]
output.extend(val.strip().split("\n"))
return normalize_messages(output)
return output

def get_suggest(self, program_text: str, incremental_step: int) -> list[tuple[str, str]]:
step_bit = "1?" if incremental_step == 1 else str(incremental_step)
Expand Down
18 changes: 16 additions & 2 deletions test-data/unit/daemon.test
Original file line number Diff line number Diff line change
Expand Up @@ -379,7 +379,7 @@ $ dmypy inspect foo.pyc:1:1:2:2
Source file is not a Python file
== Return code: 2
$ dmypy inspect bar/baz.py:1:1:2:2
Unknown module: baz
Unknown module: bar/baz.py
== Return code: 1
$ dmypy inspect foo.py:3:1:1:1
"end_line" must not be before "line"
Expand Down Expand Up @@ -434,7 +434,7 @@ $ dmypy inspect foo.pyc:1:2
Source file is not a Python file
== Return code: 2
$ dmypy inspect bar/baz.py:1:2
Unknown module: baz
Unknown module: bar/baz.py
== Return code: 1
$ dmypy inspect foo.py:7:5 --include-span
7:5:7:5 -> "int"
Expand Down Expand Up @@ -571,3 +571,17 @@ class A:
x: int
class B:
x: int

[case testDaemonInspectSelectCorrectFile]
$ dmypy run test.py --export-types
Daemon started
Success: no issues found in 1 source file
$ dmypy inspect demo/test.py:1:1
"int"
$ dmypy inspect test.py:1:1
"str"
[file test.py]
b: str
from demo.test import a
[file demo/test.py]
a: int
80 changes: 40 additions & 40 deletions test-data/unit/fine-grained-inspect.test
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
[case testInspectTypeBasic]
# inspect2: --include-kind foo.py:10:13
# inspect2: --show=type --include-kind foo.py:10:13
# inspect2: --include-span -vv foo.py:12:5
# inspect2: --include-span --include-kind foo.py:12:5:12:9
# inspect2: --include-kind tmp/foo.py:10:13
# inspect2: --show=type --include-kind tmp/foo.py:10:13
# inspect2: --include-span -vv tmp/foo.py:12:5
# inspect2: --include-span --include-kind tmp/foo.py:12:5:12:9
import foo
[file foo.py]
from typing import TypeVar, Generic
Expand All @@ -29,10 +29,10 @@ MemberExpr -> "T"
CallExpr:12:5:12:9 -> "C[int]"

[case testInspectAttrsBasic]
# inspect2: --show=attrs foo.py:6:1
# inspect2: --show=attrs foo.py:7:1
# inspect2: --show=attrs foo.py:10:1
# inspect2: --show=attrs --include-object-attrs foo.py:10:1
# inspect2: --show=attrs tmp/foo.py:6:1
# inspect2: --show=attrs tmp/foo.py:7:1
# inspect2: --show=attrs tmp/foo.py:10:1
# inspect2: --show=attrs --include-object-attrs tmp/foo.py:10:1
import foo
[file foo.py]
from bar import Meta
Expand All @@ -56,12 +56,12 @@ class Meta(type):
{"function": ["__name__"], "object": ["__init__"]}

[case testInspectDefBasic]
# inspect2: --show=definition foo.py:5:5
# inspect2: --show=definition --include-kind foo.py:6:3
# inspect2: --show=definition --include-span foo.py:7:5
# inspect2: --show=definition foo.py:8:1:8:4
# inspect2: --show=definition foo.py:8:6:8:8
# inspect2: --show=definition foo.py:9:3
# inspect2: --show=definition tmp/foo.py:5:5
# inspect2: --show=definition --include-kind tmp/foo.py:6:3
# inspect2: --show=definition --include-span tmp/foo.py:7:5
# inspect2: --show=definition tmp/foo.py:8:1:8:4
# inspect2: --show=definition tmp/foo.py:8:6:8:8
# inspect2: --show=definition tmp/foo.py:9:3
import foo
[file foo.py]
from bar import var, test, A
Expand Down Expand Up @@ -95,18 +95,18 @@ def foo(x: Union[int, str]) -> None:
[builtins fixtures/classmethod.pyi]
[out]
==
bar.py:4:0:meth
tmp/bar.py:4:0:meth
MemberExpr -> tmp/bar.py:2:5:x
7:1:7:5 -> tmp/bar.py:6:9:y
bar.py:9:1:test
bar.py:8:1:var
baz.py:3:2:foo
tmp/bar.py:9:1:test
tmp/bar.py:8:1:var
tmp/baz.py:3:2:foo

[case testInspectFallbackAttributes]
# inspect2: --show=attrs --include-object-attrs foo.py:5:1
# inspect2: --show=attrs foo.py:8:1
# inspect2: --show=attrs --include-kind foo.py:10:1
# inspect2: --show=attrs --include-kind --include-object-attrs foo.py:10:1
# inspect2: --show=attrs --include-object-attrs tmp/foo.py:5:1
# inspect2: --show=attrs tmp/foo.py:8:1
# inspect2: --show=attrs --include-kind tmp/foo.py:10:1
# inspect2: --show=attrs --include-kind --include-object-attrs tmp/foo.py:10:1
import foo
[file foo.py]
class B: ...
Expand All @@ -128,7 +128,7 @@ NameExpr -> {}
NameExpr -> {"object": ["__eq__", "__init__", "__ne__"]}

[case testInspectTypeVarBoundAttrs]
# inspect2: --show=attrs foo.py:8:13
# inspect2: --show=attrs tmp/foo.py:8:13
import foo
[file foo.py]
from typing import TypeVar
Expand All @@ -144,10 +144,10 @@ def foo(arg: T) -> T:
{"C": ["x"]}

[case testInspectTypeVarValuesAttrs]
# inspect2: --show=attrs --force-reload foo.py:13:13
# inspect2: --show=attrs --force-reload --union-attrs foo.py:13:13
# inspect2: --show=attrs foo.py:16:5
# inspect2: --show=attrs --union-attrs foo.py:16:5
# inspect2: --show=attrs --force-reload tmp/foo.py:13:13
# inspect2: --show=attrs --force-reload --union-attrs tmp/foo.py:13:13
# inspect2: --show=attrs tmp/foo.py:16:5
# inspect2: --show=attrs --union-attrs tmp/foo.py:16:5
import foo
[file foo.py]
from typing import TypeVar, Generic
Expand All @@ -174,8 +174,8 @@ class C(Generic[T]):
{"A": ["x", "z"], "B": ["y", "z"]}

[case testInspectTypeVarBoundDef]
# inspect2: --show=definition foo.py:9:13
# inspect2: --show=definition foo.py:8:9
# inspect2: --show=definition tmp/foo.py:9:13
# inspect2: --show=definition tmp/foo.py:8:9
import foo
[file foo.py]
from typing import TypeVar
Expand All @@ -189,13 +189,13 @@ def foo(arg: T) -> T:
return arg
[out]
==
foo.py:7:9:arg
foo.py:4:5:x
tmp/foo.py:7:9:arg
tmp/foo.py:4:5:x

[case testInspectTypeVarValuesDef]
# inspect2: --show=definition --force-reload foo.py:13:9
# inspect2: --show=definition --force-reload foo.py:14:13
# inspect2: --show=definition foo.py:18:7
# inspect2: --show=definition --force-reload tmp/foo.py:13:9
# inspect2: --show=definition --force-reload tmp/foo.py:14:13
# inspect2: --show=definition tmp/foo.py:18:7
import foo
[file foo.py]
from typing import TypeVar, Generic
Expand All @@ -218,12 +218,12 @@ class C(Generic[T]):
x.z
[out]
==
foo.py:5:5:z, tmp/foo.py:9:5:z
foo.py:12:9:arg
foo.py:5:5:z, tmp/foo.py:9:5:z
tmp/foo.py:5:5:z, tmp/foo.py:9:5:z
tmp/foo.py:12:9:arg
tmp/foo.py:5:5:z, tmp/foo.py:9:5:z

[case testInspectModuleAttrs]
# inspect2: --show=attrs foo.py:2:1
# inspect2: --show=attrs tmp/foo.py:2:1
import foo
[file foo.py]
from pack import bar
Expand All @@ -239,7 +239,7 @@ class C: ...
{"<pack.bar>": ["C", "__annotations__", "__doc__", "__file__", "__name__", "__package__", "bar", "x"], "ModuleType": ["__file__", "__getattr__"]}

[case testInspectModuleDef]
# inspect2: --show=definition --include-kind foo.py:2:1
# inspect2: --show=definition --include-kind tmp/foo.py:2:1
import foo
[file foo.py]
from pack import bar
Expand All @@ -255,7 +255,7 @@ NameExpr -> tmp/pack/bar.py:1:1:bar
MemberExpr -> tmp/pack/bar.py:3:5:x

[case testInspectFunctionArgDef]
# inspect2: --show=definition --include-span foo.py:4:13
# inspect2: --show=definition --include-span tmp/foo.py:4:13
# TODO: for now all arguments have line/column set to function definition.
import foo
[file foo.py]
Expand Down