From e0b65122dc92c8246de24a4db719ddbde3928e95 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 13 Aug 2024 13:52:17 +0000 Subject: [PATCH] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- .github/PULL_REQUEST_TEMPLATE.md | 11 +++++ Code_Of_Conduct.md | 19 ++++++++ Contributing.md | 11 +++++ ha_mqtt_discoverable/__init__.py | 67 +++++++--------------------- ha_mqtt_discoverable/cli/__init__.py | 12 ++--- ha_mqtt_discoverable/sensors.py | 36 ++++----------- tests/test_discoverable.py | 25 +++-------- 7 files changed, 76 insertions(+), 105 deletions(-) diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 6fe5c31..0c3b4de 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -1,3 +1,14 @@ + + +**Table of Contents** *generated with [DocToc](https://github.com/thlorenz/doctoc)* + +- [Description](#description) +- [License Acceptance](#license-acceptance) +- [Type of changes](#type-of-changes) +- [Checklist](#checklist) + + + # Description diff --git a/Code_Of_Conduct.md b/Code_Of_Conduct.md index 7b919a3..bcef317 100644 --- a/Code_Of_Conduct.md +++ b/Code_Of_Conduct.md @@ -1,3 +1,22 @@ + + +**Table of Contents** *generated with [DocToc](https://github.com/thlorenz/doctoc)* + +- [Contributor Covenant Code of Conduct](#contributor-covenant-code-of-conduct) + - [Our Pledge](#our-pledge) + - [Our Standards](#our-standards) + - [Enforcement Responsibilities](#enforcement-responsibilities) + - [Scope](#scope) + - [Enforcement](#enforcement) + - [Enforcement Guidelines](#enforcement-guidelines) + - [1. Correction](#1-correction) + - [2. Warning](#2-warning) + - [3. Temporary Ban](#3-temporary-ban) + - [4. Permanent Ban](#4-permanent-ban) + - [Attribution](#attribution) + + + # Contributor Covenant Code of Conduct ## Our Pledge diff --git a/Contributing.md b/Contributing.md index 1e0f8f8..eae2ea3 100644 --- a/Contributing.md +++ b/Contributing.md @@ -1,3 +1,14 @@ + + +**Table of Contents** *generated with [DocToc](https://github.com/thlorenz/doctoc)* + +- [Contributing](#contributing) + - [Setup](#setup) + - [Contribution Guidelines](#contribution-guidelines) + - [Linting the project files](#linting-the-project-files) + + + # Contributing ## Setup diff --git a/ha_mqtt_discoverable/__init__.py b/ha_mqtt_discoverable/__init__.py index b4b0aea..789a2bf 100644 --- a/ha_mqtt_discoverable/__init__.py +++ b/ha_mqtt_discoverable/__init__.py @@ -588,9 +588,7 @@ class Discoverable(Generic[EntityType]): availability_topic: str attributes_topic: str - def __init__( - self, settings: Settings[EntityType], on_connect: Optional[Callable] = None - ) -> None: + def __init__(self, settings: Settings[EntityType], on_connect: Optional[Callable] = None) -> None: """ Creates a basic discoverable object. @@ -613,39 +611,29 @@ def __init__( # e.g. `binary_sensor` self._entity_topic = f"{self._entity.component}" # If present, append the device name, e.g. `binary_sensor/mydevice` - self._entity_topic += ( - f"/{clean_string(self._entity.device.name)}" if self._entity.device else "" - ) + self._entity_topic += f"/{clean_string(self._entity.device.name)}" if self._entity.device else "" # Append the sensor name, e.g. `binary_sensor/mydevice/mysensor` self._entity_topic += f"/{clean_string(self._entity.name)}" # Full topic where we publish the configuration message to be picked up by HA # Prepend the `discovery_prefix`, default: `homeassistant` # e.g. homeassistant/binary_sensor/mydevice/mysensor - self.config_topic = ( - f"{self._settings.mqtt.discovery_prefix}/{self._entity_topic}/config" - ) + self.config_topic = f"{self._settings.mqtt.discovery_prefix}/{self._entity_topic}/config" # Full topic where we publish our own state messages # Prepend the `state_prefix`, default: `hmd` # e.g. hmd/binary_sensor/mydevice/mysensor - self.state_topic = ( - f"{self._settings.mqtt.state_prefix}/{self._entity_topic}/state" - ) + self.state_topic = f"{self._settings.mqtt.state_prefix}/{self._entity_topic}/state" # Full topic where we publish our own attributes as JSON messages # Prepend the `state_prefix`, default: `hmd` # e.g. hmd/binary_sensor/mydevice/mysensor - self.attributes_topic = ( - f"{self._settings.mqtt.state_prefix}/{self._entity_topic}/attributes" - ) + self.attributes_topic = f"{self._settings.mqtt.state_prefix}/{self._entity_topic}/attributes" logger.info(f"config_topic: {self.config_topic}") logger.info(f"state_topic: {self.state_topic}") if self._settings.manual_availability: # Define the availability topic, using `hmd` topic prefix - self.availability_topic = ( - f"{self._settings.mqtt.state_prefix}/{self._entity_topic}/availability" - ) + self.availability_topic = f"{self._settings.mqtt.state_prefix}/{self._entity_topic}/availability" logger.debug(f"availability_topic: {self.availability_topic}") # Create the MQTT client, registering the user `on_connect` callback @@ -671,15 +659,10 @@ def __str__(self) -> str: def _setup_client(self, on_connect: Optional[Callable] = None) -> None: """Create an MQTT client and setup some basic properties on it""" mqtt_settings = self._settings.mqtt - logger.debug( - f"Creating mqtt client ({mqtt_settings.client_name}) for " - f"{mqtt_settings.host}:{mqtt_settings.port}" - ) + logger.debug(f"Creating mqtt client ({mqtt_settings.client_name}) for " f"{mqtt_settings.host}:{mqtt_settings.port}") self.mqtt_client = mqtt.Client(mqtt_settings.client_name) if mqtt_settings.tls_key: - logger.info( - f"Connecting to {mqtt_settings.host}:{mqtt_settings.port} with SSL and client certificate authentication" - ) + logger.info(f"Connecting to {mqtt_settings.host}:{mqtt_settings.port} with SSL and client certificate authentication") logger.debug(f"ca_certs={mqtt_settings.tls_ca_cert}") logger.debug(f"certfile={mqtt_settings.tls_certfile}") logger.debug(f"keyfile={mqtt_settings.tls_key}") @@ -691,9 +674,7 @@ def _setup_client(self, on_connect: Optional[Callable] = None) -> None: tls_version=ssl.PROTOCOL_TLS, ) elif mqtt_settings.use_tls: - logger.info( - f"Connecting to {mqtt_settings.host}:{mqtt_settings.port} with SSL and username/password authentication" - ) + logger.info(f"Connecting to {mqtt_settings.host}:{mqtt_settings.port} with SSL and username/password authentication") logger.debug(f"ca_certs={mqtt_settings.tls_ca_cert}") if mqtt_settings.tls_ca_cert: self.mqtt_client.tls_set( @@ -707,17 +688,11 @@ def _setup_client(self, on_connect: Optional[Callable] = None) -> None: tls_version=ssl.PROTOCOL_TLS, ) if mqtt_settings.username: - self.mqtt_client.username_pw_set( - mqtt_settings.username, password=mqtt_settings.password - ) + self.mqtt_client.username_pw_set(mqtt_settings.username, password=mqtt_settings.password) else: - logger.debug( - f"Connecting to {mqtt_settings.host}:{mqtt_settings.port} without SSL" - ) + logger.debug(f"Connecting to {mqtt_settings.host}:{mqtt_settings.port} without SSL") if mqtt_settings.username: - self.mqtt_client.username_pw_set( - mqtt_settings.username, password=mqtt_settings.password - ) + self.mqtt_client.username_pw_set(mqtt_settings.username, password=mqtt_settings.password) if on_connect: logger.debug("Registering custom callback function") self.mqtt_client.on_connect = on_connect @@ -728,9 +703,7 @@ def _setup_client(self, on_connect: Optional[Callable] = None) -> None: def _connect_client(self) -> None: """Connect the client to the MQTT broker, start its onw internal loop in a separate thread""" - result = self.mqtt_client.connect( - self._settings.mqtt.host, self._settings.mqtt.port - ) + result = self.mqtt_client.connect(self._settings.mqtt.host, self._settings.mqtt.port) # Check if we have established a connection if result != mqtt.MQTT_ERR_SUCCESS: raise RuntimeError("Error while connecting to MQTT broker") @@ -739,9 +712,7 @@ def _connect_client(self) -> None: # messages in a separate thread self.mqtt_client.loop_start() - def _state_helper( - self, state: Optional[str], topic: Optional[str] = None, retain=True - ) -> MQTTMessageInfo: + def _state_helper(self, state: Optional[str], topic: Optional[str] = None, retain=True) -> MQTTMessageInfo: """ Write a state to the given MQTT topic, returning the result of client.publish() """ @@ -779,8 +750,7 @@ def delete(self) -> None: config_message = "" logger.info( - f"Writing '{config_message}' to topic {self.config_topic} on " - "{self._settings.mqtt.host}:{self._settings.mqtt.port}" + f"Writing '{config_message}' to topic {self.config_topic} on " "{self._settings.mqtt.host}:{self._settings.mqtt.port}" ) self.mqtt_client.publish(self.config_topic, config_message, retain=True) @@ -813,8 +783,7 @@ def write_config(self): config_message = json.dumps(self.generate_config()) logger.debug( - f"Writing '{config_message}' to topic {self.config_topic} on " - f"{self._settings.mqtt.host}:{self._settings.mqtt.port}" + f"Writing '{config_message}' to topic {self.config_topic} on " f"{self._settings.mqtt.host}:{self._settings.mqtt.port}" ) self.wrote_configuration = True self.config_message = config_message @@ -892,9 +861,7 @@ def on_client_connected(client: mqtt.Client, *args): # Invoke the parent init super().__init__(settings, on_client_connected) # Define the command topic to receive commands from HA, using `hmd` topic prefix - self._command_topic = ( - f"{self._settings.mqtt.state_prefix}/{self._entity_topic}/command" - ) + self._command_topic = f"{self._settings.mqtt.state_prefix}/{self._entity_topic}/command" # Register the user-supplied callback function with its user_data self.mqtt_client.user_data_set(user_data) diff --git a/ha_mqtt_discoverable/cli/__init__.py b/ha_mqtt_discoverable/cli/__init__.py index e6afb8c..4df314d 100644 --- a/ha_mqtt_discoverable/cli/__init__.py +++ b/ha_mqtt_discoverable/cli/__init__.py @@ -34,9 +34,7 @@ def create_base_parser(description: str = "Base parser"): choices=["DEBUG", "INFO", "ERROR", "WARNING", "CRITICAL"], default="INFO", ) - parser.add_argument( - "--client-name", type=str, help="MQTT client name", default="cephalopod" - ) + parser.add_argument("--client-name", type=str, help="MQTT client name", default="cephalopod") parser.add_argument( "--device-class", type=str, @@ -46,9 +44,7 @@ def create_base_parser(description: str = "Base parser"): parser.add_argument("--device-id", type=str, help="Device ID") parser.add_argument("--device-name", type=str, help="Device Name") parser.add_argument("--icon", type=str, help="Icon") - parser.add_argument( - "--mqtt-prefix", type=str, default="homeassistant", help="MQTT prefix" - ) + parser.add_argument("--mqtt-prefix", type=str, default="homeassistant", help="MQTT prefix") parser.add_argument("--mqtt-user", type=str, help="MQTT user.") parser.add_argument("--mqtt-password", type=str, help="MQTT password.") parser.add_argument("--mqtt-server", type=str, help="MQTT server.") @@ -60,9 +56,7 @@ def create_base_parser(description: str = "Base parser"): parser.add_argument("--tls-certfile", type=str, help="Path to certfile.") parser.add_argument("--tls-key", type=str, help="Path to tls key.") - parser.add_argument( - "--version", "-v", help="Show version and exit", action="store_true" - ) + parser.add_argument("--version", "-v", help="Show version and exit", action="store_true") return parser diff --git a/ha_mqtt_discoverable/sensors.py b/ha_mqtt_discoverable/sensors.py index 9bd58e6..d9c786d 100644 --- a/ha_mqtt_discoverable/sensors.py +++ b/ha_mqtt_discoverable/sensors.py @@ -84,9 +84,7 @@ class LightInfo(EntityInfo): component: str = "light" - state_schema: str = Field( - default="json", alias="schema" - ) # 'schema' is a reserved word by pydantic + state_schema: str = Field(default="json", alias="schema") # 'schema' is a reserved word by pydantic """Sets the schema of the state topic, ie the 'schema' field in the configuration""" optimistic: Optional[bool] = None """Flag that defines if light works in optimistic mode. @@ -251,9 +249,7 @@ def update_state(self, state: bool) -> None: state_message = self._entity.payload_on else: state_message = self._entity.payload_off - logger.info( - f"Setting {self._entity.name} to {state_message} using {self.state_topic}" - ) + logger.info(f"Setting {self._entity.name} to {state_message} using {self.state_topic}") self._state_helper(state=state_message) @@ -320,9 +316,7 @@ def brightness(self, brightness: int) -> None: brightness(int): Brightness value of [0,255] """ if brightness < 0 or brightness > 255: - raise RuntimeError( - f"Brightness for light {self._entity.name} is out of range" - ) + raise RuntimeError(f"Brightness for light {self._entity.name} is out of range") state_payload = { "brightness": brightness, @@ -342,13 +336,9 @@ def color(self, color_mode: str, color: dict[str, Any]) -> None: color(Dict[str, Any]): Color to set, according to color_mode format """ if not self._entity.color_mode: - raise RuntimeError( - f"Light {self._entity.name} does not support setting color" - ) + raise RuntimeError(f"Light {self._entity.name} does not support setting color") if color_mode not in self._entity.supported_color_modes: - raise RuntimeError( - f"Color is not in configured supported_color_modes {str(self._entity.supported_color_modes)}" - ) + raise RuntimeError(f"Color is not in configured supported_color_modes {str(self._entity.supported_color_modes)}") # We do not check if color schema conforms to color mode formatting, it is up to the caller state_payload = { "color_mode": color_mode, @@ -367,9 +357,7 @@ def effect(self, effect: str) -> None: if not self._entity.effect: raise RuntimeError(f"Light {self._entity.name} does not support effects") if effect not in self._entity.effect_list: - raise RuntimeError( - f"Effect is not within configured effect_list {str(self._entity.effect_list)}" - ) + raise RuntimeError(f"Effect is not within configured effect_list {str(self._entity.effect_list)}") state_payload = { "effect": effect, "state": self._entity.payload_on, @@ -385,9 +373,7 @@ def _update_state(self, state: dict[str, Any]) -> None: """ logger.info(f"Setting {self._entity.name} to {state} using {self.state_topic}") json_state = json.dumps(state) - self._state_helper( - state=json_state, topic=self.state_topic, retain=self._entity.retain - ) + self._state_helper(state=json_state, topic=self.state_topic, retain=self._entity.retain) class Cover(Subscriber[CoverInfo]): @@ -424,9 +410,7 @@ def _update_state(self, state: str) -> None: """ print("State: " + state) logger.info(f"Setting {self._entity.name} to {state} using {self.state_topic}") - self._state_helper( - state=state, topic=self.state_topic, retain=self._entity.retain - ) + self._state_helper(state=state, topic=self.state_topic, retain=self._entity.retain) class Button(Subscriber[ButtonInfo]): @@ -476,9 +460,7 @@ def set_text(self, text: str) -> None: """ if not self._entity.min <= len(text) <= self._entity.max: bound = f"[{self._entity.min}, {self._entity.max}]" - raise RuntimeError( - f"Text is not within configured length boundaries {bound}" - ) + raise RuntimeError(f"Text is not within configured length boundaries {bound}") logger.info(f"Setting {self._entity.name} to {text} using {self.state_topic}") self._state_helper(str(text)) diff --git a/tests/test_discoverable.py b/tests/test_discoverable.py index 05dd63e..5d314b8 100644 --- a/tests/test_discoverable.py +++ b/tests/test_discoverable.py @@ -46,9 +46,7 @@ def discoverable_availability() -> Discoverable[EntityInfo]: """Return an instance of Discoverable configured with `manual_availability`""" mqtt_settings = Settings.MQTT(host="localhost") sensor_info = EntityInfo(name="test", component="binary_sensor") - settings = Settings( - mqtt=mqtt_settings, entity=sensor_info, manual_availability=True - ) + settings = Settings(mqtt=mqtt_settings, entity=sensor_info, manual_availability=True) return Discoverable[EntityInfo](settings) @@ -114,9 +112,7 @@ def test_mqtt_topics(): def test_mqtt_topics_with_device(): mqtt_settings = Settings.MQTT(host="localhost") device = DeviceInfo(name="test_device", identifiers="id") - sensor_info = EntityInfo( - name="test", component="binary_sensor", device=device, unique_id="unique_id" - ) + sensor_info = EntityInfo(name="test", component="binary_sensor", device=device, unique_id="unique_id") settings = Settings(mqtt=mqtt_settings, entity=sensor_info) d = Discoverable[EntityInfo](settings) assert d._entity_topic == "binary_sensor/test_device/test" @@ -194,9 +190,7 @@ def test_device_without_identifiers(): def test_device_with_unique_id(): device_info = DeviceInfo(name="Test device", identifiers="test_device_id") - EntityInfo( - name="test", component="binary_sensor", unique_id="id", device=device_info - ) + EntityInfo(name="test", component="binary_sensor", unique_id="id", device=device_info) def test_name_with_space(): @@ -209,9 +203,7 @@ def test_name_with_space(): def test_custom_object_id(): mqtt_settings = Settings.MQTT(host="localhost") - sensor_info = EntityInfo( - name="Test name", component="binary_sensor", object_id="custom object id" - ) + sensor_info = EntityInfo(name="Test name", component="binary_sensor", object_id="custom object id") settings = Settings(mqtt=mqtt_settings, entity=sensor_info) d = Discoverable[EntityInfo](settings) d.write_config() @@ -306,10 +298,7 @@ def test_disconnect_client(mocker: MockerFixture): def test_set_availability_topic(discoverable_availability: Discoverable): assert discoverable_availability.availability_topic is not None - assert ( - discoverable_availability.availability_topic - == "hmd/binary_sensor/test/availability" - ) + assert discoverable_availability.availability_topic == "hmd/binary_sensor/test/availability" def test_config_availability_topic(discoverable_availability: Discoverable): @@ -322,9 +311,7 @@ def test_set_availability(discoverable_availability: Discoverable): discoverable_availability.set_availability(True) # Receive a single message, ignoring retained messages - availability_message = subscribe.simple( - discoverable_availability.availability_topic, msg_count=1, retained=False - ) + availability_message = subscribe.simple(discoverable_availability.availability_topic, msg_count=1, retained=False) assert isinstance(availability_message, MQTTMessage) assert availability_message.payload.decode("utf-8") == "online"