diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index be73c22b77d..5a5172f513f 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -360,7 +360,7 @@ jobs: - name: Run ruff run: | . venv/bin/activate - pre-commit run --hook-stage manual ruff --all-files --show-diff-on-failure + pre-commit run --hook-stage manual ruff-check --all-files --show-diff-on-failure env: RUFF_OUTPUT_FORMAT: github diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 42e05a869c3..cf896f8b12c 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,8 +1,8 @@ repos: - repo: https://github.com/astral-sh/ruff-pre-commit - rev: v0.11.0 + rev: v0.11.12 hooks: - - id: ruff + - id: ruff-check args: - --fix - id: ruff-format @@ -30,7 +30,7 @@ repos: - --branch=master - --branch=rc - repo: https://github.com/adrienverge/yamllint.git - rev: v1.35.1 + rev: v1.37.1 hooks: - id: yamllint - repo: https://github.com/pre-commit/mirrors-prettier diff --git a/.vscode/tasks.json b/.vscode/tasks.json index 09c1d374299..50bb89daf38 100644 --- a/.vscode/tasks.json +++ b/.vscode/tasks.json @@ -45,7 +45,7 @@ { "label": "Ruff", "type": "shell", - "command": "pre-commit run ruff --all-files", + "command": "pre-commit run ruff-check --all-files", "group": { "kind": "test", "isDefault": true diff --git a/homeassistant/components/amazon_devices/manifest.json b/homeassistant/components/amazon_devices/manifest.json index a24671298d9..bd9bc701d3e 100644 --- a/homeassistant/components/amazon_devices/manifest.json +++ b/homeassistant/components/amazon_devices/manifest.json @@ -118,5 +118,5 @@ "iot_class": "cloud_polling", "loggers": ["aioamazondevices"], "quality_scale": "bronze", - "requirements": ["aioamazondevices==3.0.4"] + "requirements": ["aioamazondevices==3.0.5"] } diff --git a/homeassistant/components/go2rtc/manifest.json b/homeassistant/components/go2rtc/manifest.json index 09f7b3fd74c..dd50b4ba076 100644 --- a/homeassistant/components/go2rtc/manifest.json +++ b/homeassistant/components/go2rtc/manifest.json @@ -8,6 +8,6 @@ "integration_type": "system", "iot_class": "local_polling", "quality_scale": "internal", - "requirements": ["go2rtc-client==0.1.3b0"], + "requirements": ["go2rtc-client==0.2.1"], "single_config_entry": true } diff --git a/homeassistant/components/google_mail/__init__.py b/homeassistant/components/google_mail/__init__.py index 8ef978568dc..4b530eef605 100644 --- a/homeassistant/components/google_mail/__init__.py +++ b/homeassistant/components/google_mail/__init__.py @@ -24,9 +24,11 @@ CONFIG_SCHEMA = cv.config_entry_only_config_schema(DOMAIN) async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool: - """Set up the Google Mail platform.""" + """Set up the Google Mail integration.""" hass.data.setdefault(DOMAIN, {})[DATA_HASS_CONFIG] = config + await async_setup_services(hass) + return True @@ -52,8 +54,6 @@ async def async_setup_entry(hass: HomeAssistant, entry: GoogleMailConfigEntry) - entry, [platform for platform in PLATFORMS if platform != Platform.NOTIFY] ) - await async_setup_services(hass) - return True diff --git a/homeassistant/components/google_photos/__init__.py b/homeassistant/components/google_photos/__init__.py index 40de02554ae..897598fa5cb 100644 --- a/homeassistant/components/google_photos/__init__.py +++ b/homeassistant/components/google_photos/__init__.py @@ -7,17 +7,26 @@ from google_photos_library_api.api import GooglePhotosLibraryApi from homeassistant.core import HomeAssistant from homeassistant.exceptions import ConfigEntryAuthFailed, ConfigEntryNotReady -from homeassistant.helpers import config_entry_oauth2_flow +from homeassistant.helpers import config_entry_oauth2_flow, config_validation as cv from homeassistant.helpers.aiohttp_client import async_get_clientsession +from homeassistant.helpers.typing import ConfigType from . import api from .const import DOMAIN from .coordinator import GooglePhotosConfigEntry, GooglePhotosUpdateCoordinator from .services import async_register_services -__all__ = [ - "DOMAIN", -] +__all__ = ["DOMAIN"] + +CONFIG_SCHEMA = cv.config_entry_only_config_schema(DOMAIN) + + +async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool: + """Set up Google Photos integration.""" + + async_register_services(hass) + + return True async def async_setup_entry( @@ -48,8 +57,6 @@ async def async_setup_entry( await coordinator.async_config_entry_first_refresh() entry.runtime_data = coordinator - async_register_services(hass) - return True diff --git a/homeassistant/components/google_photos/services.py b/homeassistant/components/google_photos/services.py index 8042df8f811..8b065ad34ac 100644 --- a/homeassistant/components/google_photos/services.py +++ b/homeassistant/components/google_photos/services.py @@ -152,11 +152,10 @@ def async_register_services(hass: HomeAssistant) -> None: } return None - if not hass.services.has_service(DOMAIN, UPLOAD_SERVICE): - hass.services.async_register( - DOMAIN, - UPLOAD_SERVICE, - async_handle_upload, - schema=UPLOAD_SERVICE_SCHEMA, - supports_response=SupportsResponse.OPTIONAL, - ) + hass.services.async_register( + DOMAIN, + UPLOAD_SERVICE, + async_handle_upload, + schema=UPLOAD_SERVICE_SCHEMA, + supports_response=SupportsResponse.OPTIONAL, + ) diff --git a/homeassistant/components/homekit_controller/manifest.json b/homeassistant/components/homekit_controller/manifest.json index dbcd2788c8a..d15479aa9d5 100644 --- a/homeassistant/components/homekit_controller/manifest.json +++ b/homeassistant/components/homekit_controller/manifest.json @@ -14,6 +14,6 @@ "documentation": "https://www.home-assistant.io/integrations/homekit_controller", "iot_class": "local_push", "loggers": ["aiohomekit", "commentjson"], - "requirements": ["aiohomekit==3.2.14"], + "requirements": ["aiohomekit==3.2.15"], "zeroconf": ["_hap._tcp.local.", "_hap._udp.local."] } diff --git a/homeassistant/components/homematicip_cloud/__init__.py b/homeassistant/components/homematicip_cloud/__init__.py index e460c162398..fcb71efc2b0 100644 --- a/homeassistant/components/homematicip_cloud/__init__.py +++ b/homeassistant/components/homematicip_cloud/__init__.py @@ -63,6 +63,8 @@ async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool: ) ) + await async_setup_services(hass) + return True @@ -83,7 +85,6 @@ async def async_setup_entry(hass: HomeAssistant, entry: HomematicIPConfigEntry) if not await hap.async_setup(): return False - await async_setup_services(hass) _async_remove_obsolete_entities(hass, entry, hap) # Register on HA stop event to gracefully shutdown HomematicIP Cloud connection diff --git a/homeassistant/components/homewizard/manifest.json b/homeassistant/components/homewizard/manifest.json index 51a315b2286..5d817fef837 100644 --- a/homeassistant/components/homewizard/manifest.json +++ b/homeassistant/components/homewizard/manifest.json @@ -12,6 +12,6 @@ "iot_class": "local_polling", "loggers": ["homewizard_energy"], "quality_scale": "platinum", - "requirements": ["python-homewizard-energy==v8.3.2"], + "requirements": ["python-homewizard-energy==8.3.3"], "zeroconf": ["_hwenergy._tcp.local.", "_homewizard._tcp.local."] } diff --git a/homeassistant/components/hue/__init__.py b/homeassistant/components/hue/__init__.py index 991d7b51500..cf2c1101b17 100644 --- a/homeassistant/components/hue/__init__.py +++ b/homeassistant/components/hue/__init__.py @@ -5,13 +5,24 @@ from aiohue.util import normalize_bridge_id from homeassistant.components import persistent_notification from homeassistant.config_entries import SOURCE_IGNORE from homeassistant.core import HomeAssistant -from homeassistant.helpers import device_registry as dr +from homeassistant.helpers import config_validation as cv, device_registry as dr +from homeassistant.helpers.typing import ConfigType from .bridge import HueBridge, HueConfigEntry -from .const import DOMAIN, SERVICE_HUE_ACTIVATE_SCENE +from .const import DOMAIN from .migration import check_migration from .services import async_register_services +CONFIG_SCHEMA = cv.config_entry_only_config_schema(DOMAIN) + + +async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool: + """Set up Hue integration.""" + + async_register_services(hass) + + return True + async def async_setup_entry(hass: HomeAssistant, entry: HueConfigEntry) -> bool: """Set up a bridge from a config entry.""" @@ -23,9 +34,6 @@ async def async_setup_entry(hass: HomeAssistant, entry: HueConfigEntry) -> bool: if not await bridge.async_initialize_bridge(): return False - # register Hue domain services - async_register_services(hass) - api = bridge.api # For backwards compat @@ -106,7 +114,4 @@ async def async_setup_entry(hass: HomeAssistant, entry: HueConfigEntry) -> bool: async def async_unload_entry(hass: HomeAssistant, entry: HueConfigEntry) -> bool: """Unload a config entry.""" - unload_success = await entry.runtime_data.async_reset() - if not hass.config_entries.async_loaded_entries(DOMAIN): - hass.services.async_remove(DOMAIN, SERVICE_HUE_ACTIVATE_SCENE) - return unload_success + return await entry.runtime_data.async_reset() diff --git a/homeassistant/components/hue/services.py b/homeassistant/components/hue/services.py index 3981952f16f..5875306f971 100644 --- a/homeassistant/components/hue/services.py +++ b/homeassistant/components/hue/services.py @@ -59,21 +59,20 @@ def async_register_services(hass: HomeAssistant) -> None: group_name, ) - if not hass.services.has_service(DOMAIN, SERVICE_HUE_ACTIVATE_SCENE): - # Register a local handler for scene activation - hass.services.async_register( - DOMAIN, - SERVICE_HUE_ACTIVATE_SCENE, - verify_domain_entity_control(DOMAIN)(hue_activate_scene), - schema=vol.Schema( - { - vol.Required(ATTR_GROUP_NAME): cv.string, - vol.Required(ATTR_SCENE_NAME): cv.string, - vol.Optional(ATTR_TRANSITION): cv.positive_int, - vol.Optional(ATTR_DYNAMIC): cv.boolean, - } - ), - ) + # Register a local handler for scene activation + hass.services.async_register( + DOMAIN, + SERVICE_HUE_ACTIVATE_SCENE, + verify_domain_control(hass, DOMAIN)(hue_activate_scene), + schema=vol.Schema( + { + vol.Required(ATTR_GROUP_NAME): cv.string, + vol.Required(ATTR_SCENE_NAME): cv.string, + vol.Optional(ATTR_TRANSITION): cv.positive_int, + vol.Optional(ATTR_DYNAMIC): cv.boolean, + } + ), + ) async def hue_activate_scene_v1( diff --git a/homeassistant/components/immich/media_source.py b/homeassistant/components/immich/media_source.py index c636fda879a..caf8264895b 100644 --- a/homeassistant/components/immich/media_source.py +++ b/homeassistant/components/immich/media_source.py @@ -153,49 +153,40 @@ class ImmichMediaSource(MediaSource): except ImmichError: return [] - ret = [ - BrowseMediaSource( - domain=DOMAIN, - identifier=( - f"{identifier.unique_id}|albums|" - f"{identifier.collection_id}|" - f"{asset.asset_id}|" - f"{asset.original_file_name}|" - f"{mime_type}" - ), - media_class=MediaClass.IMAGE, - media_content_type=mime_type, - title=asset.original_file_name, - can_play=False, - can_expand=False, - thumbnail=f"/immich/{identifier.unique_id}/{asset.asset_id}/thumbnail/{mime_type}", - ) - for asset in album_info.assets - if (mime_type := asset.original_mime_type) - and mime_type.startswith("image/") - ] + ret: list[BrowseMediaSource] = [] + for asset in album_info.assets: + if not (mime_type := asset.original_mime_type) or not mime_type.startswith( + ("image/", "video/") + ): + continue - ret.extend( - BrowseMediaSource( - domain=DOMAIN, - identifier=( - f"{identifier.unique_id}|albums|" - f"{identifier.collection_id}|" - f"{asset.asset_id}|" - f"{asset.original_file_name}|" - f"{mime_type}" - ), - media_class=MediaClass.VIDEO, - media_content_type=mime_type, - title=asset.original_file_name, - can_play=True, - can_expand=False, - thumbnail=f"/immich/{identifier.unique_id}/{asset.asset_id}/thumbnail/image/jpeg", + if mime_type.startswith("image/"): + media_class = MediaClass.IMAGE + can_play = False + thumb_mime_type = mime_type + else: + media_class = MediaClass.VIDEO + can_play = True + thumb_mime_type = "image/jpeg" + + ret.append( + BrowseMediaSource( + domain=DOMAIN, + identifier=( + f"{identifier.unique_id}|albums|" + f"{identifier.collection_id}|" + f"{asset.asset_id}|" + f"{asset.original_file_name}|" + f"{mime_type}" + ), + media_class=media_class, + media_content_type=mime_type, + title=asset.original_file_name, + can_play=can_play, + can_expand=False, + thumbnail=f"/immich/{identifier.unique_id}/{asset.asset_id}/thumbnail/{thumb_mime_type}", + ) ) - for asset in album_info.assets - if (mime_type := asset.original_mime_type) - and mime_type.startswith("video/") - ) return ret diff --git a/homeassistant/components/isy994/__init__.py b/homeassistant/components/isy994/__init__.py index bed86b2d0fe..5d4603cafc0 100644 --- a/homeassistant/components/isy994/__init__.py +++ b/homeassistant/components/isy994/__init__.py @@ -26,6 +26,7 @@ from homeassistant.helpers import ( device_registry as dr, ) from homeassistant.helpers.device_registry import DeviceEntryType, DeviceInfo +from homeassistant.helpers.typing import ConfigType from .const import ( _LOGGER, @@ -46,7 +47,7 @@ from .const import ( ) from .helpers import _categorize_nodes, _categorize_programs from .models import IsyConfigEntry, IsyData -from .services import async_setup_services, async_unload_services +from .services import async_setup_services from .util import _async_cleanup_registry_entries CONFIG_SCHEMA = vol.Schema( @@ -55,6 +56,14 @@ CONFIG_SCHEMA = vol.Schema( ) +async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool: + """Set up the ISY 994 integration.""" + + async_setup_services(hass) + + return True + + async def async_setup_entry(hass: HomeAssistant, entry: IsyConfigEntry) -> bool: """Set up the ISY 994 integration.""" isy_config = entry.data @@ -167,9 +176,6 @@ async def async_setup_entry(hass: HomeAssistant, entry: IsyConfigEntry) -> bool: hass.bus.async_listen_once(EVENT_HOMEASSISTANT_STOP, _async_stop_auto_update) ) - # Register Integration-wide Services: - async_setup_services(hass) - return True @@ -221,9 +227,6 @@ async def async_unload_entry(hass: HomeAssistant, entry: IsyConfigEntry) -> bool _LOGGER.debug("ISY Stopping Event Stream and automatic updates") entry.runtime_data.root.websocket.stop() - if not hass.config_entries.async_loaded_entries(DOMAIN): - async_unload_services(hass) - return unload_ok diff --git a/homeassistant/components/isy994/services.py b/homeassistant/components/isy994/services.py index 39f72a5cc2c..3f31b2e5730 100644 --- a/homeassistant/components/isy994/services.py +++ b/homeassistant/components/isy994/services.py @@ -137,10 +137,6 @@ def async_get_entities(hass: HomeAssistant) -> dict[str, Entity]: @callback def async_setup_services(hass: HomeAssistant) -> None: """Create and register services for the ISY integration.""" - existing_services = hass.services.async_services_for_domain(DOMAIN) - if existing_services and SERVICE_SEND_PROGRAM_COMMAND in existing_services: - # Integration-level services have already been added. Return. - return async def async_send_program_command_service_handler(service: ServiceCall) -> None: """Handle a send program command service call.""" @@ -230,18 +226,3 @@ def async_setup_services(hass: HomeAssistant) -> None: schema=cv.make_entity_service_schema(SERVICE_RENAME_NODE_SCHEMA), service_func=_async_rename_node, ) - - -@callback -def async_unload_services(hass: HomeAssistant) -> None: - """Unload services for the ISY integration.""" - existing_services = hass.services.async_services_for_domain(DOMAIN) - if not existing_services or SERVICE_SEND_PROGRAM_COMMAND not in existing_services: - return - - _LOGGER.debug("Unloading ISY994 Services") - hass.services.async_remove(domain=DOMAIN, service=SERVICE_SEND_PROGRAM_COMMAND) - hass.services.async_remove(domain=DOMAIN, service=SERVICE_SEND_RAW_NODE_COMMAND) - hass.services.async_remove(domain=DOMAIN, service=SERVICE_SEND_NODE_COMMAND) - hass.services.async_remove(domain=DOMAIN, service=SERVICE_GET_ZWAVE_PARAMETER) - hass.services.async_remove(domain=DOMAIN, service=SERVICE_SET_ZWAVE_PARAMETER) diff --git a/homeassistant/components/jewish_calendar/__init__.py b/homeassistant/components/jewish_calendar/__init__.py index 282614df7d3..ec73d960140 100644 --- a/homeassistant/components/jewish_calendar/__init__.py +++ b/homeassistant/components/jewish_calendar/__init__.py @@ -30,7 +30,7 @@ from .const import ( DOMAIN, ) from .entity import JewishCalendarConfigEntry, JewishCalendarData -from .service import async_setup_services +from .services import async_setup_services _LOGGER = logging.getLogger(__name__) PLATFORMS: list[Platform] = [Platform.BINARY_SENSOR, Platform.SENSOR] diff --git a/homeassistant/components/jewish_calendar/service.py b/homeassistant/components/jewish_calendar/services.py similarity index 100% rename from homeassistant/components/jewish_calendar/service.py rename to homeassistant/components/jewish_calendar/services.py diff --git a/homeassistant/components/netatmo/manifest.json b/homeassistant/components/netatmo/manifest.json index 13beb1330e4..595c57b1b4b 100644 --- a/homeassistant/components/netatmo/manifest.json +++ b/homeassistant/components/netatmo/manifest.json @@ -12,5 +12,5 @@ "integration_type": "hub", "iot_class": "cloud_polling", "loggers": ["pyatmo"], - "requirements": ["pyatmo==9.2.0"] + "requirements": ["pyatmo==9.2.1"] } diff --git a/homeassistant/components/ollama/manifest.json b/homeassistant/components/ollama/manifest.json index c3f7616ca16..87713ce3f62 100644 --- a/homeassistant/components/ollama/manifest.json +++ b/homeassistant/components/ollama/manifest.json @@ -8,5 +8,5 @@ "documentation": "https://www.home-assistant.io/integrations/ollama", "integration_type": "service", "iot_class": "local_polling", - "requirements": ["ollama==0.4.7"] + "requirements": ["ollama==0.5.1"] } diff --git a/homeassistant/components/onedrive/services.py b/homeassistant/components/onedrive/services.py index 1f1afe1507c..0b1afe925d2 100644 --- a/homeassistant/components/onedrive/services.py +++ b/homeassistant/components/onedrive/services.py @@ -121,11 +121,10 @@ def async_register_services(hass: HomeAssistant) -> None: return {"files": [asdict(item_result) for item_result in upload_results]} return None - if not hass.services.has_service(DOMAIN, UPLOAD_SERVICE): - hass.services.async_register( - DOMAIN, - UPLOAD_SERVICE, - async_handle_upload, - schema=UPLOAD_SERVICE_SCHEMA, - supports_response=SupportsResponse.OPTIONAL, - ) + hass.services.async_register( + DOMAIN, + UPLOAD_SERVICE, + async_handle_upload, + schema=UPLOAD_SERVICE_SCHEMA, + supports_response=SupportsResponse.OPTIONAL, + ) diff --git a/homeassistant/components/overkiz/manifest.json b/homeassistant/components/overkiz/manifest.json index 6f1af6d5aca..48f06ffe353 100644 --- a/homeassistant/components/overkiz/manifest.json +++ b/homeassistant/components/overkiz/manifest.json @@ -13,7 +13,7 @@ "integration_type": "hub", "iot_class": "local_polling", "loggers": ["boto3", "botocore", "pyhumps", "pyoverkiz", "s3transfer"], - "requirements": ["pyoverkiz==1.17.1"], + "requirements": ["pyoverkiz==1.17.2"], "zeroconf": [ { "type": "_kizbox._tcp.local.", diff --git a/homeassistant/components/picnic/__init__.py b/homeassistant/components/picnic/__init__.py index 8de407133cd..2d1c05c8b1a 100644 --- a/homeassistant/components/picnic/__init__.py +++ b/homeassistant/components/picnic/__init__.py @@ -5,14 +5,25 @@ from python_picnic_api2 import PicnicAPI from homeassistant.config_entries import ConfigEntry from homeassistant.const import CONF_ACCESS_TOKEN, CONF_COUNTRY_CODE, Platform from homeassistant.core import HomeAssistant +from homeassistant.helpers import config_validation as cv +from homeassistant.helpers.typing import ConfigType from .const import CONF_API, CONF_COORDINATOR, DOMAIN from .coordinator import PicnicUpdateCoordinator from .services import async_register_services +CONFIG_SCHEMA = cv.config_entry_only_config_schema(DOMAIN) PLATFORMS = [Platform.SENSOR, Platform.TODO] +async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool: + """Set up Picnic integration.""" + + await async_register_services(hass) + + return True + + def create_picnic_client(entry: ConfigEntry): """Create an instance of the PicnicAPI client.""" return PicnicAPI( @@ -37,9 +48,6 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: await hass.config_entries.async_forward_entry_setups(entry, PLATFORMS) - # Register the services - await async_register_services(hass) - return True diff --git a/homeassistant/components/picnic/services.py b/homeassistant/components/picnic/services.py index 76d7b8a6c44..9496a9441e5 100644 --- a/homeassistant/components/picnic/services.py +++ b/homeassistant/components/picnic/services.py @@ -29,9 +29,6 @@ class PicnicServiceException(Exception): async def async_register_services(hass: HomeAssistant) -> None: """Register services for the Picnic integration, if not registered yet.""" - if hass.services.has_service(DOMAIN, SERVICE_ADD_PRODUCT_TO_CART): - return - async def async_add_product_service(call: ServiceCall): api_client = await get_api_client(hass, call.data[ATTR_CONFIG_ENTRY_ID]) await handle_add_product(hass, api_client, call) diff --git a/homeassistant/components/rehlko/manifest.json b/homeassistant/components/rehlko/manifest.json index 24c9608e661..d73f8c42584 100644 --- a/homeassistant/components/rehlko/manifest.json +++ b/homeassistant/components/rehlko/manifest.json @@ -13,5 +13,5 @@ "iot_class": "cloud_polling", "loggers": ["aiokem"], "quality_scale": "silver", - "requirements": ["aiokem==0.5.12"] + "requirements": ["aiokem==1.0.1"] } diff --git a/homeassistant/components/shelly/button.py b/homeassistant/components/shelly/button.py index 44f81cc8b36..eab7514514d 100644 --- a/homeassistant/components/shelly/button.py +++ b/homeassistant/components/shelly/button.py @@ -7,7 +7,7 @@ from dataclasses import dataclass from functools import partial from typing import TYPE_CHECKING, Any, Final -from aioshelly.const import BLU_TRV_IDENTIFIER, MODEL_BLU_GATEWAY, RPC_GENERATIONS +from aioshelly.const import BLU_TRV_IDENTIFIER, MODEL_BLU_GATEWAY_G3, RPC_GENERATIONS from aioshelly.exceptions import DeviceConnectionError, InvalidAuthError, RpcCallError from homeassistant.components.button import ( @@ -62,7 +62,7 @@ BUTTONS: Final[list[ShellyButtonDescription[Any]]] = [ translation_key="self_test", entity_category=EntityCategory.DIAGNOSTIC, press_action="trigger_shelly_gas_self_test", - supported=lambda coordinator: coordinator.device.model in SHELLY_GAS_MODELS, + supported=lambda coordinator: coordinator.model in SHELLY_GAS_MODELS, ), ShellyButtonDescription[ShellyBlockCoordinator]( key="mute", @@ -70,7 +70,7 @@ BUTTONS: Final[list[ShellyButtonDescription[Any]]] = [ translation_key="mute", entity_category=EntityCategory.CONFIG, press_action="trigger_shelly_gas_mute", - supported=lambda coordinator: coordinator.device.model in SHELLY_GAS_MODELS, + supported=lambda coordinator: coordinator.model in SHELLY_GAS_MODELS, ), ShellyButtonDescription[ShellyBlockCoordinator]( key="unmute", @@ -78,7 +78,7 @@ BUTTONS: Final[list[ShellyButtonDescription[Any]]] = [ translation_key="unmute", entity_category=EntityCategory.CONFIG, press_action="trigger_shelly_gas_unmute", - supported=lambda coordinator: coordinator.device.model in SHELLY_GAS_MODELS, + supported=lambda coordinator: coordinator.model in SHELLY_GAS_MODELS, ), ] @@ -89,7 +89,7 @@ BLU_TRV_BUTTONS: Final[list[ShellyButtonDescription]] = [ translation_key="calibrate", entity_category=EntityCategory.CONFIG, press_action="trigger_blu_trv_calibration", - supported=lambda coordinator: coordinator.device.model == MODEL_BLU_GATEWAY, + supported=lambda coordinator: coordinator.model == MODEL_BLU_GATEWAY_G3, ), ] @@ -160,6 +160,7 @@ async def async_setup_entry( ShellyBluTrvButton(coordinator, button, id_) for id_ in blutrv_key_ids for button in BLU_TRV_BUTTONS + if button.supported(coordinator) ) async_add_entities(entities) diff --git a/homeassistant/components/synology_dsm/__init__.py b/homeassistant/components/synology_dsm/__init__.py index d9319beb595..b3b40d975ce 100644 --- a/homeassistant/components/synology_dsm/__init__.py +++ b/homeassistant/components/synology_dsm/__init__.py @@ -12,7 +12,8 @@ from synology_dsm.exceptions import SynologyDSMNotLoggedInException from homeassistant.const import CONF_MAC, CONF_SCAN_INTERVAL, CONF_VERIFY_SSL from homeassistant.core import HomeAssistant from homeassistant.exceptions import ConfigEntryNotReady -from homeassistant.helpers import device_registry as dr +from homeassistant.helpers import config_validation as cv, device_registry as dr +from homeassistant.helpers.typing import ConfigType from .common import SynoApi, raise_config_entry_auth_error from .const import ( @@ -34,10 +35,20 @@ from .coordinator import ( SynologyDSMData, SynologyDSMSwitchUpdateCoordinator, ) -from .service import async_setup_services +from .services import async_setup_services _LOGGER = logging.getLogger(__name__) +CONFIG_SCHEMA = cv.config_entry_only_config_schema(DOMAIN) + + +async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool: + """Set up the Synology DSM component.""" + + await async_setup_services(hass) + + return True + async def async_setup_entry(hass: HomeAssistant, entry: SynologyDSMConfigEntry) -> bool: """Set up Synology DSM sensors.""" @@ -89,9 +100,6 @@ async def async_setup_entry(hass: HomeAssistant, entry: SynologyDSMConfigEntry) details = EXCEPTION_UNKNOWN raise ConfigEntryNotReady(details) from err - # Services - await async_setup_services(hass) - # For SSDP compat if not entry.data.get(CONF_MAC): hass.config_entries.async_update_entry( diff --git a/homeassistant/components/synology_dsm/service.py b/homeassistant/components/synology_dsm/services.py similarity index 100% rename from homeassistant/components/synology_dsm/service.py rename to homeassistant/components/synology_dsm/services.py diff --git a/homeassistant/package_constraints.txt b/homeassistant/package_constraints.txt index 56102285914..b212e808724 100644 --- a/homeassistant/package_constraints.txt +++ b/homeassistant/package_constraints.txt @@ -6,7 +6,7 @@ aiodns==3.4.0 aiohasupervisor==0.3.1 aiohttp-asyncmdnsresolver==0.1.1 aiohttp-fast-zlib==0.2.3 -aiohttp==3.12.6 +aiohttp==3.12.7 aiohttp_cors==0.8.1 aiousbwatcher==1.1.1 aiozoneinfo==0.2.3 @@ -32,7 +32,7 @@ cronsim==2.6 cryptography==45.0.3 dbus-fast==2.43.0 fnv-hash-fast==1.5.0 -go2rtc-client==0.1.3b0 +go2rtc-client==0.2.1 ha-ffmpeg==3.2.2 habluetooth==3.48.2 hass-nabucasa==0.101.0 @@ -66,7 +66,7 @@ securetar==2025.2.1 SQLAlchemy==2.0.41 standard-aifc==3.13.0 standard-telnetlib==3.13.0 -typing-extensions>=4.13.0,<5.0 +typing-extensions>=4.14.0,<5.0 ulid-transform==1.4.0 urllib3>=1.26.5,<2 uv==0.7.1 diff --git a/pyproject.toml b/pyproject.toml index f8f5135c640..6291ef5193a 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -28,7 +28,7 @@ dependencies = [ # change behavior based on presence of supervisor. Deprecated with #127228 # Lib can be removed with 2025.11 "aiohasupervisor==0.3.1", - "aiohttp==3.12.6", + "aiohttp==3.12.7", "aiohttp_cors==0.8.1", "aiohttp-fast-zlib==0.2.3", "aiohttp-asyncmdnsresolver==0.1.1", @@ -111,7 +111,7 @@ dependencies = [ "SQLAlchemy==2.0.41", "standard-aifc==3.13.0", "standard-telnetlib==3.13.0", - "typing-extensions>=4.13.0,<5.0", + "typing-extensions>=4.14.0,<5.0", "ulid-transform==1.4.0", # Constrain urllib3 to ensure we deal with CVE-2020-26137 and CVE-2021-33503 # Temporary setting an upper bound, to prevent compat issues with urllib3>=2 @@ -530,18 +530,20 @@ filterwarnings = [ # https://github.com/DataDog/datadogpy/pull/290 - >=0.23.0 "ignore:invalid escape sequence:SyntaxWarning:.*datadog.dogstatsd.base", # https://github.com/DataDog/datadogpy/pull/566/files - >=0.37.0 - "ignore:pkg_resources is deprecated as an API:DeprecationWarning:datadog.util.compat", + "ignore:pkg_resources is deprecated as an API:UserWarning:datadog.util.compat", # https://github.com/httplib2/httplib2/pull/226 - >=0.21.0 "ignore:ssl.PROTOCOL_TLS is deprecated:DeprecationWarning:httplib2", - # https://github.com/influxdata/influxdb-client-python/issues/603 >=1.45.0 - # https://github.com/influxdata/influxdb-client-python/pull/652 - "ignore:datetime.*utcfromtimestamp\\(\\) is deprecated and scheduled for removal:DeprecationWarning:influxdb_client.client.write.point", # https://github.com/majuss/lupupy/pull/15 - >0.3.2 "ignore:\"is not\" with 'str' literal. Did you mean \"!=\"?:SyntaxWarning:.*lupupy.devices.alarm", # https://github.com/nextcord/nextcord/pull/1095 - >=3.0.0 - "ignore:pkg_resources is deprecated as an API:DeprecationWarning:nextcord.health_check", + "ignore:pkg_resources is deprecated as an API:UserWarning:nextcord.health_check", # https://github.com/vacanza/python-holidays/discussions/1800 - >1.0.0 "ignore::DeprecationWarning:holidays", + # https://github.com/ReactiveX/RxPY/pull/716 - >4.0.4 + "ignore:datetime.*utcfromtimestamp\\(\\) is deprecated and scheduled for removal:DeprecationWarning:reactivex.internal.constants", + # https://github.com/postlund/pyatv/issues/2645 - >0.16.0 + # https://github.com/postlund/pyatv/pull/2664 + "ignore:Protobuf gencode .* exactly one major version older than the runtime version 6.* at pyatv:UserWarning:google.protobuf.runtime_version", # https://github.com/rytilahti/python-miio/pull/1809 - >=0.6.0.dev0 "ignore:datetime.*utcnow\\(\\) is deprecated and scheduled for removal:DeprecationWarning:miio.protocol", "ignore:datetime.*utcnow\\(\\) is deprecated and scheduled for removal:DeprecationWarning:miio.miioprotocol", @@ -549,6 +551,8 @@ filterwarnings = [ "ignore:functools.partial will be a method descriptor in future Python versions; wrap it in enum.member\\(\\) if you want to preserve the old behavior:FutureWarning:miio.miot_device", # https://github.com/okunishinishi/python-stringcase/commit/6a5c5bbd3fe5337862abc7fd0853a0f36e18b2e1 - >1.2.0 "ignore:invalid escape sequence:SyntaxWarning:.*stringcase", + # https://github.com/xchwarze/samsung-tv-ws-api/pull/151 - >2.7.2 - 2024-12-06 # wrong stacklevel in aiohttp + "ignore:verify_ssl is deprecated, use ssl=False instead:DeprecationWarning:aiohttp.client", # -- other # Locale changes might take some time to resolve upstream @@ -580,6 +584,8 @@ filterwarnings = [ "ignore:getReadersFromUrls is deprecated. Please use get_readers_from_urls instead:DeprecationWarning:pysnmp.smi.compiler", # https://github.com/Python-roborock/python-roborock/issues/305 - 2.18.0 - 2025-04-06 "ignore:Callback API version 1 is deprecated, update to latest version:DeprecationWarning:roborock.cloud_api", + # https://github.com/Teslemetry/python-tesla-fleet-api - v1.1.1 - 2025-05-29 + "ignore:Protobuf gencode .* exactly one major version older than the runtime version 6.* at (car_server|common|errors|keys|managed_charging|signatures|universal_message|vcsec|vehicle):UserWarning:google.protobuf.runtime_version", # https://github.com/briis/pyweatherflowudp/blob/v1.4.5/pyweatherflowudp/const.py#L20 - v1.4.5 - 2023-10-10 "ignore:This function will be removed in future versions of pint:DeprecationWarning:pyweatherflowudp.const", # New in aiohttp - v3.9.0 @@ -602,14 +608,12 @@ filterwarnings = [ # https://pypi.org/project/sleekxmppfs/ - v1.4.1 - 2022-08-18 "ignore:invalid escape sequence:SyntaxWarning:.*sleekxmppfs.thirdparty.mini_dateutil", # codespell:ignore thirdparty # - pkg_resources - # https://pypi.org/project/aiomusiccast/ - v0.14.8 - 2023-03-20 - "ignore:pkg_resources is deprecated as an API:DeprecationWarning:aiomusiccast", # https://github.com/eavanvalkenburg/pysiaalarm/blob/v3.1.1/src/pysiaalarm/data/data.py#L7 - v3.1.1 - 2023-04-17 - "ignore:pkg_resources is deprecated as an API:DeprecationWarning:pysiaalarm.data.data", + "ignore:pkg_resources is deprecated as an API:UserWarning:pysiaalarm.data.data", # https://pypi.org/project/pybotvac/ - v0.0.26 - 2025-02-26 - "ignore:pkg_resources is deprecated as an API:DeprecationWarning:pybotvac.version", + "ignore:pkg_resources is deprecated as an API:UserWarning:pybotvac.version", # https://github.com/home-assistant-ecosystem/python-mystrom/blob/2.2.0/pymystrom/__init__.py#L10 - v2.2.0 - 2023-05-21 - "ignore:pkg_resources is deprecated as an API:DeprecationWarning:pymystrom", + "ignore:pkg_resources is deprecated as an API:UserWarning:pymystrom", # -- New in Python 3.13 # https://github.com/kurtmckee/feedparser/pull/389 - >6.0.11 @@ -640,8 +644,6 @@ filterwarnings = [ "ignore:datetime.*utcnow\\(\\) is deprecated and scheduled for removal:DeprecationWarning:directv.models", # https://pypi.org/project/enocean/ - v0.50.1 (installed) -> v0.60.1 - 2021-06-18 "ignore:It looks like you're using an HTML parser to parse an XML document:UserWarning:enocean.protocol.eep", - # https://pypi.org/project/httpsig/ - v1.3.0 - 2018-11-28 - "ignore:pkg_resources is deprecated as an API:DeprecationWarning:httpsig", # https://pypi.org/project/influxdb/ - v5.3.2 - 2024-04-18 (archived) "ignore:datetime.*utcfromtimestamp\\(\\) is deprecated and scheduled for removal:DeprecationWarning:influxdb.line_protocol", # https://pypi.org/project/lark-parser/ - v0.12.0 - 2021-08-30 -> moved to `lark` @@ -657,7 +659,7 @@ filterwarnings = [ # https://pypi.org/project/opuslib/ - v3.0.1 - 2018-01-16 "ignore:\"is not\" with 'int' literal. Did you mean \"!=\"?:SyntaxWarning:.*opuslib.api.decoder", # https://pypi.org/project/pilight/ - v0.1.1 - 2016-10-19 - "ignore:pkg_resources is deprecated as an API:DeprecationWarning:pilight", + "ignore:pkg_resources is deprecated as an API:UserWarning:pilight", # https://pypi.org/project/plumlightpad/ - v0.0.11 - 2018-10-16 "ignore:invalid escape sequence:SyntaxWarning:.*plumlightpad.plumdiscovery", "ignore:\"is\" with 'int' literal. Did you mean \"==\"?:SyntaxWarning:.*plumlightpad.(lightpad|logicalload)", @@ -672,8 +674,6 @@ filterwarnings = [ # https://pypi.org/project/pyqwikswitch/ - v0.94 - 2019-08-19 "ignore:client.loop property is deprecated:DeprecationWarning:pyqwikswitch.async_", "ignore:with timeout\\(\\) is deprecated:DeprecationWarning:pyqwikswitch.async_", - # https://pypi.org/project/Rx/ - v3.2.0 - 2021-04-25 - "ignore:datetime.*utcfromtimestamp\\(\\) is deprecated and scheduled for removal:DeprecationWarning:rx.internal.constants", # https://pypi.org/project/rxv/ - v0.7.0 - 2021-10-10 "ignore:defusedxml.cElementTree is deprecated, import from defusedxml.ElementTree instead:DeprecationWarning:rxv.ssdp", ] diff --git a/requirements.txt b/requirements.txt index 8df7d081854..bbb0ec6f107 100644 --- a/requirements.txt +++ b/requirements.txt @@ -5,7 +5,7 @@ # Home Assistant Core aiodns==3.4.0 aiohasupervisor==0.3.1 -aiohttp==3.12.6 +aiohttp==3.12.7 aiohttp_cors==0.8.1 aiohttp-fast-zlib==0.2.3 aiohttp-asyncmdnsresolver==0.1.1 @@ -51,7 +51,7 @@ securetar==2025.2.1 SQLAlchemy==2.0.41 standard-aifc==3.13.0 standard-telnetlib==3.13.0 -typing-extensions>=4.13.0,<5.0 +typing-extensions>=4.14.0,<5.0 ulid-transform==1.4.0 urllib3>=1.26.5,<2 uv==0.7.1 diff --git a/requirements_all.txt b/requirements_all.txt index 4ea9c2188bf..9d942d4832d 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -182,7 +182,7 @@ aioairzone-cloud==0.6.12 aioairzone==1.0.0 # homeassistant.components.amazon_devices -aioamazondevices==3.0.4 +aioamazondevices==3.0.5 # homeassistant.components.ambient_network # homeassistant.components.ambient_station @@ -268,7 +268,7 @@ aiohasupervisor==0.3.1 aiohomeconnect==0.17.1 # homeassistant.components.homekit_controller -aiohomekit==3.2.14 +aiohomekit==3.2.15 # homeassistant.components.mcp_server aiohttp_sse==2.2.0 @@ -289,7 +289,7 @@ aiokafka==0.10.0 aiokef==0.2.16 # homeassistant.components.rehlko -aiokem==0.5.12 +aiokem==1.0.1 # homeassistant.components.lifx aiolifx-effects==0.3.2 @@ -1026,7 +1026,7 @@ gitterpy==0.1.7 glances-api==0.8.0 # homeassistant.components.go2rtc -go2rtc-client==0.1.3b0 +go2rtc-client==0.2.1 # homeassistant.components.goalzero goalzero==0.2.2 @@ -1572,7 +1572,7 @@ oemthermostat==1.1.1 ohme==1.5.1 # homeassistant.components.ollama -ollama==0.4.7 +ollama==0.5.1 # homeassistant.components.omnilogic omnilogic==0.4.5 @@ -1841,7 +1841,7 @@ pyasuswrt==0.1.21 pyatag==0.3.5.3 # homeassistant.components.netatmo -pyatmo==9.2.0 +pyatmo==9.2.1 # homeassistant.components.apple_tv pyatv==0.16.0 @@ -2221,7 +2221,7 @@ pyotgw==2.2.2 pyotp==2.8.0 # homeassistant.components.overkiz -pyoverkiz==1.17.1 +pyoverkiz==1.17.2 # homeassistant.components.onewire pyownet==0.10.0.post1 @@ -2434,7 +2434,7 @@ python-google-drive-api==0.1.0 python-homeassistant-analytics==0.9.0 # homeassistant.components.homewizard -python-homewizard-energy==v8.3.2 +python-homewizard-energy==8.3.3 # homeassistant.components.hp_ilo python-hpilo==4.4.3 diff --git a/requirements_test.txt b/requirements_test.txt index e5c9796c86b..c0494d93705 100644 --- a/requirements_test.txt +++ b/requirements_test.txt @@ -10,7 +10,7 @@ astroid==3.3.10 coverage==7.8.2 freezegun==1.5.2 -go2rtc-client==0.1.3b0 +go2rtc-client==0.2.1 license-expression==30.4.1 mock-open==1.4.0 mypy-dev==1.17.0a2 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index 1c3c7183cce..51b33a3df62 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -170,7 +170,7 @@ aioairzone-cloud==0.6.12 aioairzone==1.0.0 # homeassistant.components.amazon_devices -aioamazondevices==3.0.4 +aioamazondevices==3.0.5 # homeassistant.components.ambient_network # homeassistant.components.ambient_station @@ -253,7 +253,7 @@ aiohasupervisor==0.3.1 aiohomeconnect==0.17.1 # homeassistant.components.homekit_controller -aiohomekit==3.2.14 +aiohomekit==3.2.15 # homeassistant.components.mcp_server aiohttp_sse==2.2.0 @@ -271,7 +271,7 @@ aioimmich==0.8.0 aiokafka==0.10.0 # homeassistant.components.rehlko -aiokem==0.5.12 +aiokem==1.0.1 # homeassistant.components.lifx aiolifx-effects==0.3.2 @@ -887,7 +887,7 @@ gios==6.0.0 glances-api==0.8.0 # homeassistant.components.go2rtc -go2rtc-client==0.1.3b0 +go2rtc-client==0.2.1 # homeassistant.components.goalzero goalzero==0.2.2 @@ -1334,7 +1334,7 @@ odp-amsterdam==6.1.1 ohme==1.5.1 # homeassistant.components.ollama -ollama==0.4.7 +ollama==0.5.1 # homeassistant.components.omnilogic omnilogic==0.4.5 @@ -1540,7 +1540,7 @@ pyasuswrt==0.1.21 pyatag==0.3.5.3 # homeassistant.components.netatmo -pyatmo==9.2.0 +pyatmo==9.2.1 # homeassistant.components.apple_tv pyatv==0.16.0 @@ -1842,7 +1842,7 @@ pyotgw==2.2.2 pyotp==2.8.0 # homeassistant.components.overkiz -pyoverkiz==1.17.1 +pyoverkiz==1.17.2 # homeassistant.components.onewire pyownet==0.10.0.post1 @@ -2007,7 +2007,7 @@ python-google-drive-api==0.1.0 python-homeassistant-analytics==0.9.0 # homeassistant.components.homewizard -python-homewizard-energy==v8.3.2 +python-homewizard-energy==8.3.3 # homeassistant.components.izone python-izone==1.2.9 diff --git a/requirements_test_pre_commit.txt b/requirements_test_pre_commit.txt index ff86915bbf3..ba05be7043b 100644 --- a/requirements_test_pre_commit.txt +++ b/requirements_test_pre_commit.txt @@ -1,5 +1,5 @@ # Automatically generated from .pre-commit-config.yaml by gen_requirements_all.py, do not edit codespell==2.4.1 -ruff==0.11.0 -yamllint==1.35.1 +ruff==0.11.12 +yamllint==1.37.1 diff --git a/script/gen_requirements_all.py b/script/gen_requirements_all.py index 572e57b999e..f4c2ee8da6a 100755 --- a/script/gen_requirements_all.py +++ b/script/gen_requirements_all.py @@ -249,6 +249,10 @@ GENERATED_MESSAGE = ( f"# Automatically generated by {Path(__file__).name}, do not edit\n\n" ) +MAP_HOOK_ID_TO_PACKAGE = { + "ruff-check": "ruff", +} + IGNORE_PRE_COMMIT_HOOK_ID = ( "check-executables-have-shebangs", "check-json", @@ -523,7 +527,8 @@ def requirements_pre_commit_output() -> str: rev: str = repo["rev"] for hook in repo["hooks"]: if hook["id"] not in IGNORE_PRE_COMMIT_HOOK_ID: - reqs.append(f"{hook['id']}=={rev.lstrip('v')}") + pkg = MAP_HOOK_ID_TO_PACKAGE.get(hook["id"]) or hook["id"] + reqs.append(f"{pkg}=={rev.lstrip('v')}") reqs.extend(x for x in hook.get("additional_dependencies", ())) output = [ f"# Automatically generated " diff --git a/script/hassfest/docker/Dockerfile b/script/hassfest/docker/Dockerfile index 08260f3b9a2..ac4d9c256f2 100644 --- a/script/hassfest/docker/Dockerfile +++ b/script/hassfest/docker/Dockerfile @@ -24,8 +24,8 @@ RUN --mount=from=ghcr.io/astral-sh/uv:0.7.1,source=/uv,target=/bin/uv \ --no-cache \ -c /usr/src/homeassistant/homeassistant/package_constraints.txt \ -r /usr/src/homeassistant/requirements.txt \ - stdlib-list==0.10.0 pipdeptree==2.26.1 tqdm==4.67.1 ruff==0.11.0 \ - PyTurboJPEG==1.8.0 go2rtc-client==0.1.3b0 ha-ffmpeg==3.2.2 hassil==2.2.3 home-assistant-intents==2025.5.28 mutagen==1.47.0 pymicro-vad==1.0.1 pyspeex-noise==1.0.2 + stdlib-list==0.10.0 pipdeptree==2.26.1 tqdm==4.67.1 ruff==0.11.12 \ + PyTurboJPEG==1.8.0 go2rtc-client==0.2.1 ha-ffmpeg==3.2.2 hassil==2.2.3 home-assistant-intents==2025.5.28 mutagen==1.47.0 pymicro-vad==1.0.1 pyspeex-noise==1.0.2 LABEL "name"="hassfest" LABEL "maintainer"="Home Assistant " diff --git a/script/hassfest/requirements.py b/script/hassfest/requirements.py index 33898a13910..1b6aef6f787 100644 --- a/script/hassfest/requirements.py +++ b/script/hassfest/requirements.py @@ -26,6 +26,7 @@ from .model import Config, Integration PACKAGE_CHECK_VERSION_RANGE = { "aiohttp": "SemVer", "attrs": "CalVer", + "awesomeversion": "CalVer", "grpcio": "SemVer", "httpx": "SemVer", "mashumaro": "SemVer", @@ -40,13 +41,9 @@ PACKAGE_CHECK_VERSION_RANGE_EXCEPTIONS: dict[str, dict[str, set[str]]] = { # - domain is the integration domain # - package is the package (can be transitive) referencing the dependency # - dependencyX should be the name of the referenced dependency - "ollama": { - # https://github.com/ollama/ollama-python/pull/445 (not yet released) - "ollama": {"httpx"} - }, - "overkiz": { - # https://github.com/iMicknl/python-overkiz-api/issues/1644 (not yet released) - "pyoverkiz": {"attrs"}, + "mealie": { + # https://github.com/joostlek/python-mealie/pull/490 + "aiomealie": {"awesomeversion"} }, } @@ -333,14 +330,6 @@ PYTHON_VERSION_CHECK_EXCEPTIONS: dict[str, dict[str, set[str]]] = { # https://github.com/EuleMitKeule/eq3btsmart/releases/tag/2.0.0 "homeassistant": {"eq3btsmart"} }, - "homekit_controller": { - # https://github.com/Jc2k/aiohomekit/issues/456 - "homeassistant": {"aiohomekit"} - }, - "netatmo": { - # https://github.com/jabesq-org/pyatmo/pull/533 (not yet released) - "homeassistant": {"pyatmo"} - }, "python_script": { # Security audits are needed for each Python version "homeassistant": {"restrictedpython"} diff --git a/script/licenses.py b/script/licenses.py index 9932e61b080..c3b9399d6b8 100644 --- a/script/licenses.py +++ b/script/licenses.py @@ -196,6 +196,7 @@ EXCEPTIONS = { "maxcube-api", # https://github.com/uebelack/python-maxcube-api/pull/48 "neurio", # https://github.com/jordanh/neurio-python/pull/13 "nsw-fuel-api-client", # https://github.com/nickw444/nsw-fuel-api-client/pull/14 + "ollama", # https://github.com/ollama/ollama-python/pull/526 "pigpio", # https://github.com/joan2937/pigpio/pull/608 "pymitv", # MIT "pybbox", # https://github.com/HydrelioxGitHub/pybbox/pull/5 diff --git a/script/lint b/script/lint index daafedb2297..26b6db705f1 100755 --- a/script/lint +++ b/script/lint @@ -15,7 +15,7 @@ printf "%s\n" $files echo "==============" echo "LINT with ruff" echo "==============" -pre-commit run ruff --files $files +pre-commit run ruff-check --files $files echo "================" echo "LINT with pylint" echo "================"