From e61142c2c2ce88bcfca3b141a77635e5d681c653 Mon Sep 17 00:00:00 2001 From: epenet <6771947+epenet@users.noreply.github.com> Date: Tue, 17 Dec 2024 12:53:27 +0100 Subject: [PATCH] Check if requirement is typed in strict_typing IQS validation (#133415) * Check if requirement is typed in strict_typing IQS validation * Apply suggestions from code review * Apply suggestions from code review * Return a list * Adjust * Improve --- .../components/fritz/quality_scale.yaml | 5 +++- .../components/imap/quality_scale.yaml | 5 +++- .../components/mastodon/quality_scale.yaml | 5 +++- .../components/mqtt/quality_scale.yaml | 5 +++- .../components/stookwijzer/quality_scale.yaml | 5 +++- .../quality_scale_validation/strict_typing.py | 29 +++++++++++++++++++ 6 files changed, 49 insertions(+), 5 deletions(-) diff --git a/homeassistant/components/fritz/quality_scale.yaml b/homeassistant/components/fritz/quality_scale.yaml index b832492cf9d..06c572f93a6 100644 --- a/homeassistant/components/fritz/quality_scale.yaml +++ b/homeassistant/components/fritz/quality_scale.yaml @@ -95,4 +95,7 @@ rules: comment: | the fritzconnection lib is not async and relies on requests changing this might need a bit more efforts to be spent - strict-typing: done + strict-typing: + status: todo + comment: | + Requirements 'fritzconnection==1.14.0' and 'xmltodict==0.13.0' appear untyped diff --git a/homeassistant/components/imap/quality_scale.yaml b/homeassistant/components/imap/quality_scale.yaml index 180aef93f91..1c75b527882 100644 --- a/homeassistant/components/imap/quality_scale.yaml +++ b/homeassistant/components/imap/quality_scale.yaml @@ -94,4 +94,7 @@ rules: status: exempt comment: | This integration does not use web sessions. - strict-typing: done + strict-typing: + status: todo + comment: | + Requirement 'aioimaplib==1.1.0' appears untyped diff --git a/homeassistant/components/mastodon/quality_scale.yaml b/homeassistant/components/mastodon/quality_scale.yaml index 315ef808701..86702095e95 100644 --- a/homeassistant/components/mastodon/quality_scale.yaml +++ b/homeassistant/components/mastodon/quality_scale.yaml @@ -93,4 +93,7 @@ rules: # Platinum async-dependency: todo inject-websession: todo - strict-typing: done + strict-typing: + status: todo + comment: | + Requirement 'Mastodon.py==1.8.1' appears untyped diff --git a/homeassistant/components/mqtt/quality_scale.yaml b/homeassistant/components/mqtt/quality_scale.yaml index f31d3e25d15..26ce8cb08dd 100644 --- a/homeassistant/components/mqtt/quality_scale.yaml +++ b/homeassistant/components/mqtt/quality_scale.yaml @@ -125,4 +125,7 @@ rules: status: exempt comment: | This integration does not use web sessions. - strict-typing: done + strict-typing: + status: todo + comment: | + Requirement 'paho-mqtt==1.6.1' appears untyped diff --git a/homeassistant/components/stookwijzer/quality_scale.yaml b/homeassistant/components/stookwijzer/quality_scale.yaml index 67fadc00b64..20e64efaa92 100644 --- a/homeassistant/components/stookwijzer/quality_scale.yaml +++ b/homeassistant/components/stookwijzer/quality_scale.yaml @@ -86,4 +86,7 @@ rules: # Platinum async-dependency: done inject-websession: done - strict-typing: done + strict-typing: + status: todo + comment: | + Requirement 'stookwijzer==1.5.1' appears untyped diff --git a/script/hassfest/quality_scale_validation/strict_typing.py b/script/hassfest/quality_scale_validation/strict_typing.py index a27ab752cf0..c1373032ff8 100644 --- a/script/hassfest/quality_scale_validation/strict_typing.py +++ b/script/hassfest/quality_scale_validation/strict_typing.py @@ -4,6 +4,7 @@ https://developers.home-assistant.io/docs/core/integration-quality-scale/rules/s """ from functools import lru_cache +from importlib import metadata from pathlib import Path import re @@ -24,6 +25,29 @@ def _strict_typing_components(strict_typing_file: Path) -> set[str]: ) +def _check_requirements_are_typed(integration: Integration) -> list[str]: + """Check if all requirements are typed.""" + invalid_requirements = [] + for requirement in integration.requirements: + requirement_name, requirement_version = requirement.split("==") + # Remove any extras + requirement_name = requirement_name.split("[")[0] + try: + distribution = metadata.distribution(requirement_name) + except metadata.PackageNotFoundError: + # Package not installed locally + continue + if distribution.version != requirement_version: + # Version out of date locally + continue + + if not any(file for file in distribution.files if file.name == "py.typed"): + # no py.typed file + invalid_requirements.append(requirement) + + return invalid_requirements + + def validate( config: Config, integration: Integration, *, rules_done: set[str] ) -> list[str] | None: @@ -35,4 +59,9 @@ def validate( "Integration does not have strict typing enabled " "(is missing from .strict-typing)" ] + if untyped_requirements := _check_requirements_are_typed(integration): + return [ + f"Requirements {untyped_requirements} do not conform PEP 561 (https://peps.python.org/pep-0561/)", + "They should be typed and have a 'py.typed' file", + ] return None