Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 18 additions & 4 deletions mypy/build.py
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@
from mypy.report import Reports # Avoid unconditional slow import

from mypy import errorcodes as codes
from mypy.config_parser import parse_mypy_comments
from mypy.config_parser import get_config_module_names, parse_mypy_comments
from mypy.fixup import fixup_module
from mypy.freetree import free_tree
from mypy.fscache import FileSystemCache
Expand Down Expand Up @@ -472,6 +472,7 @@ def build_inner(
dump_timing_stats(options.timing_stats, graph)
if options.line_checking_stats is not None:
dump_line_checking_stats(options.line_checking_stats, graph)
warn_unused_configs(options, flush_errors)
return BuildResult(manager, graph)
finally:
t0 = time.time()
Expand All @@ -496,6 +497,19 @@ def build_inner(
record_missing_stub_packages(options.cache_dir, manager.missing_stub_packages)


def warn_unused_configs(
options: Options, flush_errors: Callable[[str | None, list[str], bool], None]
) -> None:
if options.warn_unused_configs and options.unused_configs and not options.non_interactive:
unused = get_config_module_names(
options.config_file,
[glob for glob in options.per_module_options.keys() if glob in options.unused_configs],
)
flush_errors(
None, ["{}: note: unused section(s): {}".format(options.config_file, unused)], False
)


def default_data_dir() -> str:
"""Returns directory containing typeshed directory."""
return os.path.dirname(__file__)
Expand Down Expand Up @@ -3783,7 +3797,7 @@ def load_graph(
manager.missing_modules.add(dep)
# TODO: for now we skip this in the daemon as a performance optimization.
# This however creates a correctness issue, see #7777 and State.is_fresh().
if not manager.use_fine_grained_cache():
if not manager.use_fine_grained_cache() or manager.options.warn_unused_configs:
manager.import_options[dep] = manager.options.clone_for_module(
dep
).dep_import_options()
Expand Down Expand Up @@ -3841,8 +3855,8 @@ def load_graph(
graph[newst.id] = newst
new.append(newst)
# There are two things we need to do after the initial load loop. One is up-suppress
# modules that are back in graph. We need to do this after the loop to cover an edge
# case where a namespace package ancestor is shared by a typed and an untyped package.
# modules that are back in graph. We need to do this after the loop to cover edge cases
# like where a namespace package ancestor is shared by a typed and an untyped package.
for st in graph.values():
for dep in st.suppressed:
if dep in graph:
Expand Down
5 changes: 2 additions & 3 deletions mypy/ipc.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,9 +48,8 @@ class IPCBase:
This contains logic shared between the client and server, such as reading
and writing.
We want to be able to send multiple "messages" over a single connection and
to be able to separate the messages. We do this by encoding the messages
in an alphabet that does not contain spaces, then adding a space for
separation. The last framed message is also followed by a space.
to be able to separate the messages. We do this by prefixing each message
with its size in a fixed format.
"""

connection: _IPCHandle
Expand Down
27 changes: 1 addition & 26 deletions mypy/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,7 @@
sys.exit(2)

from mypy import build, defaults, state, util
from mypy.config_parser import (
get_config_module_names,
parse_config_file,
parse_version,
validate_package_allow_list,
)
from mypy.config_parser import parse_config_file, parse_version, validate_package_allow_list
from mypy.defaults import RECURSION_LIMIT
from mypy.error_formatter import OUTPUT_CHOICES
from mypy.errors import CompileError
Expand Down Expand Up @@ -221,26 +216,6 @@ def flush_errors(filename: str | None, new_messages: list[str], serious: bool) -
blockers = True
if not e.use_stdout:
serious = True
if (
options.warn_unused_configs
and options.unused_configs
and not options.incremental
and not options.non_interactive
):
print(
"Warning: unused section(s) in {}: {}".format(
options.config_file,
get_config_module_names(
options.config_file,
[
glob
for glob in options.per_module_options.keys()
if glob in options.unused_configs
],
),
),
file=stderr,
)
maybe_write_junit_xml(time.time() - t0, serious, messages, messages_by_file, options)
return res, messages, blockers

Expand Down
52 changes: 52 additions & 0 deletions test-data/unit/check-incremental.test
Original file line number Diff line number Diff line change
Expand Up @@ -7993,3 +7993,55 @@ from a import b # type: ignore[attr-defined]
[out]
main:2: error: Unused "type: ignore" comment
[out2]

[case testConfigWarnUnusedSectionIncremental]
# flags: --config-file=tmp/mypy.ini
import m
[file m.py]
import a
[file m.py.2]
import a # touch
[file a.py]
import foo # type: ignore
[file mypy.ini]
\[mypy]
warn_unused_configs = true
\[mypy-bar]
\[mypy-foo]
[file mypy.ini.3]
\[mypy]
warn_unused_configs = true
\[mypy-foo]
[out]
tmp/mypy.ini: note: unused section(s): [mypy-bar]
[out2]
tmp/mypy.ini: note: unused section(s): [mypy-bar]
[out3]

[case testConfigWarnUnusedSectionIncrementalTOML]
# flags: --config-file tmp/pyproject.toml
import m
[file m.py]
import a
[file m.py.2]
import a # touch
[file a.py]
import foo # type: ignore
[file pyproject.toml]
\[tool.mypy]
warn_unused_configs = true
\[[tool.mypy.overrides]]
module = "bar"
\[[tool.mypy.overrides]]
module = "foo"
warn_unreachable = true
[file pyproject.toml.3]
\[tool.mypy]
warn_unused_configs = true
\[[tool.mypy.overrides]]
module = "foo"
[out]
tmp/pyproject.toml: note: unused section(s): module = ['bar']
[out2]
tmp/pyproject.toml: note: unused section(s): module = ['bar']
[out3]
3 changes: 1 addition & 2 deletions test-data/unit/cmdline.test
Original file line number Diff line number Diff line change
Expand Up @@ -529,7 +529,6 @@ variable has type "bytes")
[file mypy.ini]
\[mypy]
warn_unused_configs = True
incremental = False
\[mypy-bar]
\[mypy-foo]
\[mypy-baz.*]
Expand All @@ -549,7 +548,7 @@ incremental = False
[file spam/__init__.py]
[file spam/eggs.py]
[out]
Warning: unused section(s) in mypy.ini: [mypy-bar], [mypy-baz.*], [mypy-emarg.*], [mypy-emarg.hatch], [mypy-a.*.c], [mypy-a.x.b]
mypy.ini: note: unused section(s): [mypy-bar], [mypy-baz.*], [mypy-emarg.*], [mypy-emarg.hatch], [mypy-a.*.c], [mypy-a.x.b]
== Return code: 0

[case testPackageRootEmpty]
Expand Down