Keep mypy.ini and strict-typing files sorted with hassfest (#81331)

hassfest: keep mypy.ini and .strict-typing sorted
This commit is contained in:
Aarni Koskela 2022-11-14 07:37:47 +02:00 committed by GitHub
parent 4bf233a4c1
commit 727dcd6df6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 106 additions and 67 deletions

View File

@ -5,14 +5,10 @@
# Strict typing is enabled by default for core files.
# Add it here to add 'disallow_any_generics'.
# --- Only for core file! ---
homeassistant.exceptions
homeassistant.core
homeassistant.loader
homeassistant.requirements
homeassistant.runner
homeassistant.setup
homeassistant.auth.auth_store
homeassistant.auth.providers.*
homeassistant.core
homeassistant.exceptions
homeassistant.helpers.area_registry
homeassistant.helpers.condition
homeassistant.helpers.debounce
@ -29,6 +25,10 @@ homeassistant.helpers.script_variables
homeassistant.helpers.singleton
homeassistant.helpers.sun
homeassistant.helpers.translation
homeassistant.loader
homeassistant.requirements
homeassistant.runner
homeassistant.setup
homeassistant.util.async_
homeassistant.util.color
homeassistant.util.decorator
@ -79,9 +79,9 @@ homeassistant.components.button.*
homeassistant.components.calendar.*
homeassistant.components.camera.*
homeassistant.components.canary.*
homeassistant.components.cover.*
homeassistant.components.clickatell.*
homeassistant.components.clicksend.*
homeassistant.components.cover.*
homeassistant.components.cpuspeed.*
homeassistant.components.crownstone.*
homeassistant.components.deconz.*
@ -215,9 +215,9 @@ homeassistant.components.prusalink.*
homeassistant.components.pure_energie.*
homeassistant.components.pvoutput.*
homeassistant.components.qnap_qsw.*
homeassistant.components.radarr.*
homeassistant.components.rainmachine.*
homeassistant.components.rdw.*
homeassistant.components.radarr.*
homeassistant.components.recollect_waste.*
homeassistant.components.recorder.*
homeassistant.components.remote.*

View File

@ -28,28 +28,16 @@ warn_unreachable = true
[mypy-homeassistant.*]
no_implicit_reexport = true
[mypy-homeassistant.exceptions]
[mypy-homeassistant.auth.auth_store]
disallow_any_generics = true
[mypy-homeassistant.auth.providers.*]
disallow_any_generics = true
[mypy-homeassistant.core]
disallow_any_generics = true
[mypy-homeassistant.loader]
disallow_any_generics = true
[mypy-homeassistant.requirements]
disallow_any_generics = true
[mypy-homeassistant.runner]
disallow_any_generics = true
[mypy-homeassistant.setup]
disallow_any_generics = true
[mypy-homeassistant.auth.auth_store]
disallow_any_generics = true
[mypy-homeassistant.auth.providers.*]
[mypy-homeassistant.exceptions]
disallow_any_generics = true
[mypy-homeassistant.helpers.area_registry]
@ -100,6 +88,18 @@ disallow_any_generics = true
[mypy-homeassistant.helpers.translation]
disallow_any_generics = true
[mypy-homeassistant.loader]
disallow_any_generics = true
[mypy-homeassistant.requirements]
disallow_any_generics = true
[mypy-homeassistant.runner]
disallow_any_generics = true
[mypy-homeassistant.setup]
disallow_any_generics = true
[mypy-homeassistant.util.async_]
disallow_any_generics = true
@ -543,16 +543,6 @@ disallow_untyped_defs = true
warn_return_any = true
warn_unreachable = true
[mypy-homeassistant.components.cover.*]
check_untyped_defs = true
disallow_incomplete_defs = true
disallow_subclassing_any = true
disallow_untyped_calls = true
disallow_untyped_decorators = true
disallow_untyped_defs = true
warn_return_any = true
warn_unreachable = true
[mypy-homeassistant.components.clickatell.*]
check_untyped_defs = true
disallow_incomplete_defs = true
@ -573,6 +563,16 @@ disallow_untyped_defs = true
warn_return_any = true
warn_unreachable = true
[mypy-homeassistant.components.cover.*]
check_untyped_defs = true
disallow_incomplete_defs = true
disallow_subclassing_any = true
disallow_untyped_calls = true
disallow_untyped_decorators = true
disallow_untyped_defs = true
warn_return_any = true
warn_unreachable = true
[mypy-homeassistant.components.cpuspeed.*]
check_untyped_defs = true
disallow_incomplete_defs = true
@ -1903,6 +1903,16 @@ disallow_untyped_defs = true
warn_return_any = true
warn_unreachable = true
[mypy-homeassistant.components.radarr.*]
check_untyped_defs = true
disallow_incomplete_defs = true
disallow_subclassing_any = true
disallow_untyped_calls = true
disallow_untyped_decorators = true
disallow_untyped_defs = true
warn_return_any = true
warn_unreachable = true
[mypy-homeassistant.components.rainmachine.*]
check_untyped_defs = true
disallow_incomplete_defs = true
@ -1923,16 +1933,6 @@ disallow_untyped_defs = true
warn_return_any = true
warn_unreachable = true
[mypy-homeassistant.components.radarr.*]
check_untyped_defs = true
disallow_incomplete_defs = true
disallow_subclassing_any = true
disallow_untyped_calls = true
disallow_untyped_decorators = true
disallow_untyped_defs = true
warn_return_any = true
warn_unreachable = true
[mypy-homeassistant.components.recollect_waste.*]
check_untyped_defs = true
disallow_incomplete_defs = true

View File

@ -1,6 +1,7 @@
"""Generate mypy config."""
from __future__ import annotations
from collections.abc import Iterable
import configparser
import io
import os
@ -90,18 +91,48 @@ def _strict_module_in_ignore_list(
return None
def generate_and_validate(config: Config) -> str:
def _sort_within_sections(line_iter: Iterable[str]) -> Iterable[str]:
"""
Sort lines within sections.
Sections are defined as anything not delimited by a blank line
or an octothorpe-prefixed comment line.
"""
section: list[str] = []
for line in line_iter:
if line.startswith("#") or not line.strip():
yield from sorted(section)
section.clear()
yield line
continue
section.append(line)
yield from sorted(section)
def _get_strict_typing_path(config: Config) -> Path:
return config.root / ".strict-typing"
def _get_mypy_ini_path(config: Config) -> Path:
return config.root / "mypy.ini"
def _generate_and_validate_strict_typing(config: Config) -> str:
"""Validate and generate strict_typing."""
lines = [
line.strip()
for line in _get_strict_typing_path(config).read_text().splitlines()
]
return "\n".join(_sort_within_sections(lines)) + "\n"
def _generate_and_validate_mypy_config(config: Config) -> str:
"""Validate and generate mypy config."""
config_path = config.root / ".strict-typing"
with config_path.open() as fp:
lines = fp.readlines()
# Filter empty and commented lines.
parsed_modules: list[str] = [
line.strip()
for line in lines
for line in config.cache["strict_typing"].splitlines()
if line.strip() != "" and not line.startswith("#")
]
@ -210,28 +241,36 @@ def generate_and_validate(config: Config) -> str:
with io.StringIO() as fp:
mypy_config.write(fp)
fp.seek(0)
return HEADER + fp.read().strip()
return f"{HEADER}{fp.read().strip()}\n"
def validate(integrations: dict[str, Integration], config: Config) -> None:
"""Validate mypy config."""
config_path = config.root / "mypy.ini"
config.cache["mypy_config"] = content = generate_and_validate(config)
"""Validate strict_typing and mypy config."""
strict_typing_content = _generate_and_validate_strict_typing(config)
config.cache["strict_typing"] = strict_typing_content
mypy_content = _generate_and_validate_mypy_config(config)
config.cache["mypy_config"] = mypy_content
if any(err.plugin == "mypy_config" for err in config.errors):
return
with open(str(config_path)) as fp:
if fp.read().strip() != content:
config.add_error(
"mypy_config",
"File mypy.ini is not up to date. Run python3 -m script.hassfest",
fixable=True,
)
if _get_strict_typing_path(config).read_text() != strict_typing_content:
config.add_error(
"mypy_config",
"File .strict_typing is not up to date. Run python3 -m script.hassfest",
fixable=True,
)
if _get_mypy_ini_path(config).read_text() != mypy_content:
config.add_error(
"mypy_config",
"File mypy.ini is not up to date. Run python3 -m script.hassfest",
fixable=True,
)
def generate(integrations: dict[str, Integration], config: Config) -> None:
"""Generate mypy config."""
config_path = config.root / "mypy.ini"
with open(str(config_path), "w") as fp:
fp.write(f"{config.cache['mypy_config']}\n")
"""Generate strict_typing and mypy config."""
_get_mypy_ini_path(config).write_text(config.cache["mypy_config"])
_get_strict_typing_path(config).write_text(config.cache["strict_typing"])