diff --git a/.coveragerc b/.coveragerc index d51cc28c7fc77..e32db823542fa 100644 --- a/.coveragerc +++ b/.coveragerc @@ -1,3 +1,7 @@ +# Sorted by hassfest. +# +# To sort, run python3 -m script.hassfest -p coverage + [run] source = homeassistant omit = @@ -103,10 +107,10 @@ omit = homeassistant/components/aurora/sensor.py homeassistant/components/avea/light.py homeassistant/components/avion/light.py + homeassistant/components/awair/coordinator.py homeassistant/components/azure_devops/__init__.py homeassistant/components/azure_devops/sensor.py homeassistant/components/azure_service_bus/* - homeassistant/components/awair/coordinator.py homeassistant/components/baf/__init__.py homeassistant/components/baf/climate.py homeassistant/components/baf/entity.py @@ -190,8 +194,8 @@ omit = homeassistant/components/comelit/alarm_control_panel.py homeassistant/components/comelit/climate.py homeassistant/components/comelit/const.py - homeassistant/components/comelit/cover.py homeassistant/components/comelit/coordinator.py + homeassistant/components/comelit/cover.py homeassistant/components/comelit/humidifier.py homeassistant/components/comelit/light.py homeassistant/components/comelit/sensor.py @@ -239,8 +243,8 @@ omit = homeassistant/components/dominos/* homeassistant/components/doods/* homeassistant/components/doorbird/__init__.py - homeassistant/components/doorbird/camera.py homeassistant/components/doorbird/button.py + homeassistant/components/doorbird/camera.py homeassistant/components/doorbird/device.py homeassistant/components/doorbird/entity.py homeassistant/components/doorbird/util.py @@ -260,12 +264,12 @@ omit = homeassistant/components/dunehd/__init__.py homeassistant/components/dunehd/media_player.py homeassistant/components/duotecno/__init__.py - homeassistant/components/duotecno/entity.py - homeassistant/components/duotecno/switch.py + homeassistant/components/duotecno/binary_sensor.py + homeassistant/components/duotecno/climate.py homeassistant/components/duotecno/cover.py + homeassistant/components/duotecno/entity.py homeassistant/components/duotecno/light.py - homeassistant/components/duotecno/climate.py - homeassistant/components/duotecno/binary_sensor.py + homeassistant/components/duotecno/switch.py homeassistant/components/dwd_weather_warnings/const.py homeassistant/components/dwd_weather_warnings/coordinator.py homeassistant/components/dwd_weather_warnings/sensor.py @@ -305,10 +309,12 @@ omit = homeassistant/components/edl21/__init__.py homeassistant/components/edl21/sensor.py homeassistant/components/egardia/* + homeassistant/components/electrasmart/__init__.py + homeassistant/components/electrasmart/climate.py homeassistant/components/electric_kiwi/__init__.py homeassistant/components/electric_kiwi/api.py - homeassistant/components/electric_kiwi/oauth2.py homeassistant/components/electric_kiwi/coordinator.py + homeassistant/components/electric_kiwi/oauth2.py homeassistant/components/electric_kiwi/select.py homeassistant/components/eliqonline/sensor.py homeassistant/components/elkm1/__init__.py @@ -381,11 +387,11 @@ omit = homeassistant/components/ezviz/binary_sensor.py homeassistant/components/ezviz/button.py homeassistant/components/ezviz/camera.py + homeassistant/components/ezviz/coordinator.py + homeassistant/components/ezviz/entity.py homeassistant/components/ezviz/image.py homeassistant/components/ezviz/light.py - homeassistant/components/ezviz/coordinator.py homeassistant/components/ezviz/number.py - homeassistant/components/ezviz/entity.py homeassistant/components/ezviz/select.py homeassistant/components/ezviz/sensor.py homeassistant/components/ezviz/siren.py @@ -534,8 +540,8 @@ omit = homeassistant/components/hive/switch.py homeassistant/components/hive/water_heater.py homeassistant/components/hko/__init__.py - homeassistant/components/hko/weather.py homeassistant/components/hko/coordinator.py + homeassistant/components/hko/weather.py homeassistant/components/hlk_sw16/__init__.py homeassistant/components/hlk_sw16/switch.py homeassistant/components/home_connect/__init__.py @@ -573,9 +579,9 @@ omit = homeassistant/components/hunterdouglas_powerview/sensor.py homeassistant/components/hunterdouglas_powerview/shade_data.py homeassistant/components/hunterdouglas_powerview/util.py - homeassistant/components/hvv_departures/__init__.py homeassistant/components/huum/__init__.py homeassistant/components/huum/climate.py + homeassistant/components/hvv_departures/__init__.py homeassistant/components/hvv_departures/binary_sensor.py homeassistant/components/hvv_departures/sensor.py homeassistant/components/ialarm/alarm_control_panel.py @@ -668,9 +674,9 @@ omit = homeassistant/components/keyboard/* homeassistant/components/keyboard_remote/* homeassistant/components/keymitt_ble/__init__.py + homeassistant/components/keymitt_ble/coordinator.py homeassistant/components/keymitt_ble/entity.py homeassistant/components/keymitt_ble/switch.py - homeassistant/components/keymitt_ble/coordinator.py homeassistant/components/kitchen_sink/weather.py homeassistant/components/kiwi/lock.py homeassistant/components/kodi/__init__.py @@ -841,8 +847,15 @@ omit = homeassistant/components/mysensors/switch.py homeassistant/components/mystrom/binary_sensor.py homeassistant/components/mystrom/light.py - homeassistant/components/mystrom/switch.py homeassistant/components/mystrom/sensor.py + homeassistant/components/mystrom/switch.py + homeassistant/components/myuplink/__init__.py + homeassistant/components/myuplink/api.py + homeassistant/components/myuplink/application_credentials.py + homeassistant/components/myuplink/coordinator.py + homeassistant/components/myuplink/entity.py + homeassistant/components/myuplink/helpers.py + homeassistant/components/myuplink/sensor.py homeassistant/components/nad/media_player.py homeassistant/components/nanoleaf/__init__.py homeassistant/components/nanoleaf/button.py @@ -850,13 +863,13 @@ omit = homeassistant/components/nanoleaf/light.py homeassistant/components/neato/__init__.py homeassistant/components/neato/api.py + homeassistant/components/neato/button.py homeassistant/components/neato/camera.py homeassistant/components/neato/entity.py homeassistant/components/neato/hub.py homeassistant/components/neato/sensor.py homeassistant/components/neato/switch.py homeassistant/components/neato/vacuum.py - homeassistant/components/neato/button.py homeassistant/components/nederlandse_spoorwegen/sensor.py homeassistant/components/netdata/sensor.py homeassistant/components/netgear/__init__.py @@ -966,10 +979,10 @@ omit = homeassistant/components/openweathermap/weather.py homeassistant/components/openweathermap/weather_update_coordinator.py homeassistant/components/opnsense/__init__.py + homeassistant/components/opnsense/device_tracker.py homeassistant/components/opower/__init__.py homeassistant/components/opower/coordinator.py homeassistant/components/opower/sensor.py - homeassistant/components/opnsense/device_tracker.py homeassistant/components/opple/light.py homeassistant/components/oru/* homeassistant/components/orvibo/switch.py @@ -1096,17 +1109,6 @@ omit = homeassistant/components/rainmachine/switch.py homeassistant/components/rainmachine/update.py homeassistant/components/rainmachine/util.py - homeassistant/components/renson/__init__.py - homeassistant/components/renson/const.py - homeassistant/components/renson/coordinator.py - homeassistant/components/renson/entity.py - homeassistant/components/renson/sensor.py - homeassistant/components/renson/button.py - homeassistant/components/renson/fan.py - homeassistant/components/renson/switch.py - homeassistant/components/renson/binary_sensor.py - homeassistant/components/renson/number.py - homeassistant/components/renson/time.py homeassistant/components/raspyrfm/* homeassistant/components/recollect_waste/sensor.py homeassistant/components/recorder/repack.py @@ -1121,6 +1123,17 @@ omit = homeassistant/components/rejseplanen/sensor.py homeassistant/components/remember_the_milk/__init__.py homeassistant/components/remote_rpi_gpio/* + homeassistant/components/renson/__init__.py + homeassistant/components/renson/binary_sensor.py + homeassistant/components/renson/button.py + homeassistant/components/renson/const.py + homeassistant/components/renson/coordinator.py + homeassistant/components/renson/entity.py + homeassistant/components/renson/fan.py + homeassistant/components/renson/number.py + homeassistant/components/renson/sensor.py + homeassistant/components/renson/switch.py + homeassistant/components/renson/time.py homeassistant/components/reolink/binary_sensor.py homeassistant/components/reolink/button.py homeassistant/components/reolink/camera.py @@ -1164,11 +1177,11 @@ omit = homeassistant/components/route53/* homeassistant/components/rpi_camera/* homeassistant/components/rtorrent/sensor.py + homeassistant/components/russound_rio/media_player.py + homeassistant/components/russound_rnet/media_player.py homeassistant/components/ruuvi_gateway/__init__.py homeassistant/components/ruuvi_gateway/bluetooth.py homeassistant/components/ruuvi_gateway/coordinator.py - homeassistant/components/russound_rio/media_player.py - homeassistant/components/russound_rnet/media_player.py homeassistant/components/rympro/__init__.py homeassistant/components/rympro/coordinator.py homeassistant/components/rympro/sensor.py @@ -1179,8 +1192,8 @@ omit = homeassistant/components/schluter/* homeassistant/components/screenlogic/binary_sensor.py homeassistant/components/screenlogic/climate.py - homeassistant/components/screenlogic/coordinator.py homeassistant/components/screenlogic/const.py + homeassistant/components/screenlogic/coordinator.py homeassistant/components/screenlogic/entity.py homeassistant/components/screenlogic/light.py homeassistant/components/screenlogic/number.py @@ -1255,8 +1268,8 @@ omit = homeassistant/components/solaredge/coordinator.py homeassistant/components/solaredge_local/sensor.py homeassistant/components/solarlog/__init__.py - homeassistant/components/solarlog/sensor.py homeassistant/components/solarlog/coordinator.py + homeassistant/components/solarlog/sensor.py homeassistant/components/solax/__init__.py homeassistant/components/solax/sensor.py homeassistant/components/soma/__init__.py @@ -1293,14 +1306,6 @@ omit = homeassistant/components/squeezebox/__init__.py homeassistant/components/squeezebox/browse_media.py homeassistant/components/squeezebox/media_player.py - homeassistant/components/starlink/__init__.py - homeassistant/components/starlink/binary_sensor.py - homeassistant/components/starlink/button.py - homeassistant/components/starlink/coordinator.py - homeassistant/components/starlink/device_tracker.py - homeassistant/components/starlink/sensor.py - homeassistant/components/starlink/switch.py - homeassistant/components/starlink/time.py homeassistant/components/starline/__init__.py homeassistant/components/starline/account.py homeassistant/components/starline/binary_sensor.py @@ -1311,6 +1316,14 @@ omit = homeassistant/components/starline/sensor.py homeassistant/components/starline/switch.py homeassistant/components/starlingbank/sensor.py + homeassistant/components/starlink/__init__.py + homeassistant/components/starlink/binary_sensor.py + homeassistant/components/starlink/button.py + homeassistant/components/starlink/coordinator.py + homeassistant/components/starlink/device_tracker.py + homeassistant/components/starlink/sensor.py + homeassistant/components/starlink/switch.py + homeassistant/components/starlink/time.py homeassistant/components/steam_online/sensor.py homeassistant/components/stiebel_eltron/* homeassistant/components/stookalert/__init__.py @@ -1354,9 +1367,9 @@ omit = homeassistant/components/switchbot/entity.py homeassistant/components/switchbot/humidifier.py homeassistant/components/switchbot/light.py + homeassistant/components/switchbot/lock.py homeassistant/components/switchbot/sensor.py homeassistant/components/switchbot/switch.py - homeassistant/components/switchbot/lock.py homeassistant/components/switchbot_cloud/climate.py homeassistant/components/switchbot_cloud/coordinator.py homeassistant/components/switchbot_cloud/entity.py @@ -1516,9 +1529,9 @@ omit = homeassistant/components/ue_smart_radio/media_player.py homeassistant/components/ukraine_alarm/__init__.py homeassistant/components/ukraine_alarm/binary_sensor.py - homeassistant/components/unifiled/* homeassistant/components/unifi_direct/__init__.py homeassistant/components/unifi_direct/device_tracker.py + homeassistant/components/unifiled/* homeassistant/components/upb/__init__.py homeassistant/components/upb/light.py homeassistant/components/upc_connect/* @@ -1528,7 +1541,6 @@ omit = homeassistant/components/upnp/__init__.py homeassistant/components/upnp/device.py homeassistant/components/upnp/sensor.py - homeassistant/components/vasttrafik/sensor.py homeassistant/components/v2c/__init__.py homeassistant/components/v2c/binary_sensor.py homeassistant/components/v2c/coordinator.py @@ -1536,6 +1548,7 @@ omit = homeassistant/components/v2c/number.py homeassistant/components/v2c/sensor.py homeassistant/components/v2c/switch.py + homeassistant/components/vasttrafik/sensor.py homeassistant/components/velbus/__init__.py homeassistant/components/velbus/binary_sensor.py homeassistant/components/velbus/button.py @@ -1543,8 +1556,8 @@ omit = homeassistant/components/velbus/cover.py homeassistant/components/velbus/entity.py homeassistant/components/velbus/light.py - homeassistant/components/velbus/sensor.py homeassistant/components/velbus/select.py + homeassistant/components/velbus/sensor.py homeassistant/components/velbus/switch.py homeassistant/components/velux/__init__.py homeassistant/components/velux/cover.py @@ -1710,12 +1723,12 @@ omit = homeassistant/components/zeversolar/coordinator.py homeassistant/components/zeversolar/entity.py homeassistant/components/zeversolar/sensor.py - homeassistant/components/zha/websocket_api.py homeassistant/components/zha/core/cluster_handlers/* homeassistant/components/zha/core/device.py homeassistant/components/zha/core/gateway.py homeassistant/components/zha/core/helpers.py homeassistant/components/zha/light.py + homeassistant/components/zha/websocket_api.py homeassistant/components/zhong_hong/climate.py homeassistant/components/ziggo_mediabox_xl/media_player.py homeassistant/components/zoneminder/* @@ -1732,15 +1745,6 @@ omit = homeassistant/components/zwave_me/sensor.py homeassistant/components/zwave_me/siren.py homeassistant/components/zwave_me/switch.py - homeassistant/components/electrasmart/climate.py - homeassistant/components/electrasmart/__init__.py - homeassistant/components/myuplink/__init__.py - homeassistant/components/myuplink/api.py - homeassistant/components/myuplink/application_credentials.py - homeassistant/components/myuplink/coordinator.py - homeassistant/components/myuplink/entity.py - homeassistant/components/myuplink/helpers.py - homeassistant/components/myuplink/sensor.py [report] diff --git a/script/hassfest/coverage.py b/script/hassfest/coverage.py index 64951fb028808..264960a42e102 100644 --- a/script/hassfest/coverage.py +++ b/script/hassfest/coverage.py @@ -20,6 +20,42 @@ "scene.py", ) +PREFIX = """# Sorted by hassfest. +# +# To sort, run python3 -m script.hassfest -p coverage + +[run] +source = homeassistant +omit = + homeassistant/__main__.py + homeassistant/helpers/signal.py + homeassistant/scripts/__init__.py + homeassistant/scripts/check_config.py + homeassistant/scripts/ensure_config.py + homeassistant/scripts/benchmark/__init__.py + homeassistant/scripts/macos/__init__.py + + # omit pieces of code that rely on external devices being present +""" + +SUFFIX = """[report] +# Regexes for lines to exclude from consideration +exclude_lines = + # Have to re-enable the standard pragma + pragma: no cover + + # Don't complain about missing debug-only code: + def __repr__ + + # Don't complain if tests don't hit defensive assertion code: + raise AssertionError + raise NotImplementedError + + # TYPE_CHECKING and @overload blocks are never executed during pytest run + if TYPE_CHECKING: + @overload +""" + def validate(integrations: dict[str, Integration], config: Config) -> None: """Validate coverage.""" @@ -28,6 +64,7 @@ def validate(integrations: dict[str, Integration], config: Config) -> None: not_found: list[str] = [] checking = False + previous_line = "" with coverage_path.open("rt") as fp: for line in fp: line = line.strip() @@ -55,13 +92,27 @@ def validate(integrations: dict[str, Integration], config: Config) -> None: not_found.append(line) continue - if not line.startswith("homeassistant/components/") or len(path.parts) != 4: + if not line.startswith("homeassistant/components/"): continue integration_path = path.parent + while len(integration_path.parts) > 3: + integration_path = integration_path.parent integration = integrations[integration_path.name] + # Ensure sorted + if line < previous_line: + integration.add_error( + "coverage", + f"{line} is unsorted in .coveragerc file", + ) + previous_line = line + + # Ignore sub-directories for further checks + if len(path.parts) > 4: + continue + if ( path.parts[-1] == "*" and Path(f"tests/components/{integration.domain}/__init__.py").exists() @@ -85,3 +136,28 @@ def validate(integrations: dict[str, Integration], config: Config) -> None: raise RuntimeError( f".coveragerc references files that don't exist: {', '.join(not_found)}." ) + + +def generate(integrations: dict[str, Integration], config: Config) -> None: + """Sort coverage.""" + coverage_path = config.root / ".coveragerc" + lines = [] + start = False + + with coverage_path.open("rt") as fp: + for line in fp: + if ( + not start + and line + == " # omit pieces of code that rely on external devices being present\n" + ): + start = True + elif line == "[report]\n": + break + elif start and line != "\n": + lines.append(line) + + content = f"{PREFIX}{"".join(sorted(lines))}\n\n{SUFFIX}" + + with coverage_path.open("w") as fp: + fp.write(content)