Skip to content

Commit

Permalink
Merge branch 'dev' into auto_empty
Browse files Browse the repository at this point in the history
  • Loading branch information
edenhaus authored Dec 20, 2024
2 parents 8ef39ba + 3ed2a37 commit b5d05a1
Show file tree
Hide file tree
Showing 74 changed files with 399 additions and 227 deletions.
13 changes: 10 additions & 3 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ jobs:
uses: actions/checkout@v4

- name: 🏗 Install uv and Python
uses: astral-sh/setup-uv@v4
uses: astral-sh/setup-uv@v5
with:
enable-cache: true
cache-dependency-glob: "uv.lock"
Expand Down Expand Up @@ -51,7 +51,7 @@ jobs:
uses: actions/checkout@v4

- name: 🏗 Install uv and Python ${{ matrix.python-version }}
uses: astral-sh/setup-uv@v4
uses: astral-sh/setup-uv@v5
with:
enable-cache: true
cache-dependency-glob: "uv.lock"
Expand All @@ -62,10 +62,17 @@ jobs:
run: uv sync --locked --dev

- name: Run pytest
run: uv run --frozen pytest tests --cov=./ --cov-report=xml
run: uv run --frozen pytest tests --cov=./ --cov-report=xml --junitxml=junit.xml -o junit_family=legacy

- name: Upload coverage to Codecov
uses: codecov/codecov-action@v5
with:
token: ${{ secrets.CODECOV_TOKEN }}
fail_ci_if_error: true

- name: Upload test results to Codecov
if: ${{ !cancelled() }}
uses: codecov/test-results-action@v1
with:
token: ${{ secrets.CODECOV_TOKEN }}
fail_ci_if_error: true
2 changes: 1 addition & 1 deletion .github/workflows/python-publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ jobs:
- name: ⤵️ Check out code from GitHub
uses: actions/[email protected]
- name: 🏗 Set up uv
uses: astral-sh/setup-uv@v4
uses: astral-sh/setup-uv@v5
with:
enable-cache: true
- name: 🏗 Set package version
Expand Down
2 changes: 1 addition & 1 deletion .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ default_language_version:

repos:
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.8.2
rev: v0.8.3
hooks:
- id: ruff
args:
Expand Down
2 changes: 1 addition & 1 deletion .python-version
Original file line number Diff line number Diff line change
@@ -1 +1 @@
3.13
3.13.0
47 changes: 21 additions & 26 deletions deebot_client/command.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
ApiTimeoutError,
DeebotError,
)
from deebot_client.util import verify_required_class_variables_exists

from .const import PATH_API_IOT_DEVMANAGER, REQUEST_HEADERS, DataType
from .logging_filter import get_logger
Expand Down Expand Up @@ -64,24 +65,18 @@ class Command(ABC):
"""Abstract command object."""

_targets_bot: bool = True
NAME: str
DATA_TYPE: DataType

def __init_subclass__(cls) -> None:
verify_required_class_variables_exists(cls, ("NAME", "DATA_TYPE"))
return super().__init_subclass__()

def __init__(self, args: dict[str, Any] | list[Any] | None = None) -> None:
if args is None:
args = {}
self._args = args

@property # type: ignore[misc]
@classmethod
@abstractmethod
def name(cls) -> str:
"""Command name."""

@property # type: ignore[misc]
@classmethod
@abstractmethod
def data_type(cls) -> DataType:
"""Data type."""

@abstractmethod
def _get_payload(self) -> dict[str, Any] | list[Any] | str:
"""Get the payload for the rest call."""
Expand Down Expand Up @@ -115,7 +110,7 @@ async def execute(
except Exception: # pylint: disable=broad-except
_LOGGER.warning(
"Could not execute command %s",
self.name,
self.NAME,
exc_info=True,
)
return DeviceCommandResult(device_reached=False)
Expand All @@ -132,14 +127,14 @@ async def _execute(
except ApiTimeoutError:
_LOGGER.warning(
"Could not execute command %s: Timeout reached",
self.name,
self.NAME,
)
return CommandResult(HandlingState.ERROR), {}

result = self.__handle_response(event_bus, response)
if result.state == HandlingState.ANALYSE:
_LOGGER.debug(
"ANALYSE: Could not handle command: %s with %s", self.name, response
"ANALYSE: Could not handle command: %s with %s", self.NAME, response
)
return (
CommandResult(
Expand All @@ -150,16 +145,16 @@ async def _execute(
response,
)
if result.state == HandlingState.ERROR:
_LOGGER.warning("Could not parse %s: %s", self.name, response)
_LOGGER.warning("Could not parse %s: %s", self.NAME, response)
return result, response

async def _execute_api_request(
self, authenticator: Authenticator, device_info: ApiDeviceInfo
) -> dict[str, Any]:
payload = {
"cmdName": self.name,
"cmdName": self.NAME,
"payload": self._get_payload(),
"payloadType": self.data_type.value,
"payloadType": self.DATA_TYPE.value,
"td": "q",
"toId": device_info["did"],
"toRes": device_info["resource"],
Expand Down Expand Up @@ -195,7 +190,7 @@ def __handle_response(
result = self._handle_response(event_bus, response)
if result.state == HandlingState.ANALYSE:
_LOGGER.debug(
"ANALYSE: Could not handle command: %s with %s", self.name, response
"ANALYSE: Could not handle command: %s with %s", self.NAME, response
)
return CommandResult(
HandlingState.ANALYSE_LOGGED,
Expand All @@ -206,7 +201,7 @@ def __handle_response(
except Exception: # pylint: disable=broad-except
_LOGGER.warning(
"Could not parse response for %s: %s",
self.name,
self.NAME,
response,
exc_info=True,
)
Expand All @@ -223,12 +218,12 @@ def _handle_response(

def __eq__(self, obj: object) -> bool:
if isinstance(obj, Command):
return self.name == obj.name and self._args == obj._args
return self.NAME == obj.NAME and self._args == obj._args

return False

def __hash__(self) -> int:
return hash(self.name) + hash(self._args)
return hash(self.NAME) + hash(self._args)


class CommandWithMessageHandling(Command, Message, ABC):
Expand All @@ -253,24 +248,24 @@ def _handle_response(
case 4200:
# bot offline
_LOGGER.info(
'Device is offline. Could not execute command "%s"', self.name
'Device is offline. Could not execute command "%s"', self.NAME
)
event_bus.notify(AvailabilityEvent(available=False))
return CommandResult(HandlingState.FAILED)
case 500:
if self._is_available_check:
_LOGGER.info(
'No response received for command "%s" during availability-check.',
self.name,
self.NAME,
)
else:
_LOGGER.warning(
'No response received for command "%s". This can happen if the device has network issues or does not support the command',
self.name,
self.NAME,
)
return CommandResult(HandlingState.FAILED)

_LOGGER.warning('Command "%s" was not successfully.', self.name)
_LOGGER.warning('Command "%s" was not successfully.', self.NAME)
return CommandResult(HandlingState.ANALYSE)


Expand Down
5 changes: 1 addition & 4 deletions deebot_client/commands/json/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -234,10 +234,7 @@
]
# fmt: on

COMMANDS: dict[str, type[Command]] = {
cmd.name: cmd # type: ignore[misc]
for cmd in _COMMANDS
}
COMMANDS: dict[str, type[Command]] = {cmd.NAME: cmd for cmd in _COMMANDS}

COMMANDS_WITH_MQTT_P2P_HANDLING: dict[str, type[CommandMqttP2P]] = {
cmd_name: cmd
Expand Down
6 changes: 3 additions & 3 deletions deebot_client/commands/json/advanced_mode.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,12 @@
class GetAdvancedMode(GetEnableCommand):
"""Get advanced mode command."""

name = "getAdvancedMode"
event_type = AdvancedModeEvent
NAME = "getAdvancedMode"
EVENT_TYPE = AdvancedModeEvent


class SetAdvancedMode(SetEnableCommand):
"""Set advanced mode command."""

name = "setAdvancedMode"
NAME = "setAdvancedMode"
get_command = GetAdvancedMode
2 changes: 1 addition & 1 deletion deebot_client/commands/json/battery.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
class GetBattery(OnBattery, JsonCommandWithMessageHandling):
"""Get battery command."""

name = "getBattery"
NAME = "getBattery"

def __init__(self, *, is_available_check: bool = False) -> None:
super().__init__()
Expand Down
6 changes: 3 additions & 3 deletions deebot_client/commands/json/border_switch.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,12 @@
class GetBorderSwitch(GetEnableCommand):
"""Get border switch command."""

name = "getBorderSwitch"
event_type = BorderSwitchEvent
NAME = "getBorderSwitch"
EVENT_TYPE = BorderSwitchEvent


class SetBorderSwitch(SetEnableCommand):
"""Set border switch command."""

name = "setBorderSwitch"
NAME = "setBorderSwitch"
get_command = GetBorderSwitch
6 changes: 3 additions & 3 deletions deebot_client/commands/json/carpet.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,12 @@
class GetCarpetAutoFanBoost(GetEnableCommand):
"""Get carpet auto fan boost command."""

name = "getCarpertPressure"
event_type = CarpetAutoFanBoostEvent
NAME = "getCarpertPressure"
EVENT_TYPE = CarpetAutoFanBoostEvent


class SetCarpetAutoFanBoost(SetEnableCommand):
"""Set carpet auto fan boost command."""

name = "setCarpertPressure"
NAME = "setCarpertPressure"
get_command = GetCarpetAutoFanBoost
2 changes: 1 addition & 1 deletion deebot_client/commands/json/charge.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
class Charge(ExecuteCommand):
"""Charge command."""

name = "charge"
NAME = "charge"

def __init__(self) -> None:
super().__init__({"act": "go"})
Expand Down
2 changes: 1 addition & 1 deletion deebot_client/commands/json/charge_state.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
class GetChargeState(JsonCommandWithMessageHandling, MessageBodyDataDict):
"""Get charge state command."""

name = "getChargeState"
NAME = "getChargeState"

@classmethod
def _handle_body_data_dict(
Expand Down
6 changes: 3 additions & 3 deletions deebot_client/commands/json/child_lock.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,14 @@
class GetChildLock(GetEnableCommand):
"""Get child lock command."""

name = "getChildLock"
event_type = ChildLockEvent
NAME = "getChildLock"
EVENT_TYPE = ChildLockEvent
_field_name = "on"


class SetChildLock(SetEnableCommand):
"""Set child lock command."""

name = "setChildLock"
NAME = "setChildLock"
get_command = GetChildLock
_field_name = "on"
8 changes: 4 additions & 4 deletions deebot_client/commands/json/clean.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
class Clean(ExecuteCommand):
"""Clean command."""

name = "clean"
NAME = "clean"

def __init__(self, action: CleanAction) -> None:
super().__init__(self._get_args(action))
Expand Down Expand Up @@ -77,7 +77,7 @@ def _get_args(self, action: CleanAction) -> dict[str, Any]:
class CleanV2(Clean):
"""Clean V2 command."""

name = "clean_V2"
NAME = "clean_V2"

def _get_args(self, action: CleanAction) -> dict[str, Any]:
content: dict[str, str] = {}
Expand Down Expand Up @@ -107,7 +107,7 @@ def _get_args(self, action: CleanAction) -> dict[str, Any]:
class GetCleanInfo(JsonCommandWithMessageHandling, MessageBodyDataDict):
"""Get clean info command."""

name = "getCleanInfo"
NAME = "getCleanInfo"

@classmethod
def _handle_body_data_dict(
Expand Down Expand Up @@ -158,4 +158,4 @@ def _handle_body_data_dict(
class GetCleanInfoV2(GetCleanInfo):
"""Get clean info v2 command."""

name = "getCleanInfo_V2"
NAME = "getCleanInfo_V2"
4 changes: 2 additions & 2 deletions deebot_client/commands/json/clean_count.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
class GetCleanCount(JsonGetCommand):
"""Get clean count command."""

name = "getCleanCount"
NAME = "getCleanCount"

@classmethod
def _handle_body_data_dict(
Expand All @@ -35,7 +35,7 @@ def _handle_body_data_dict(
class SetCleanCount(JsonSetCommand):
"""Set clean count command."""

name = "setCleanCount"
NAME = "setCleanCount"
get_command = GetCleanCount
_mqtt_params = MappingProxyType({"count": InitParam(int)})

Expand Down
4 changes: 2 additions & 2 deletions deebot_client/commands/json/clean_logs.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ class GetCleanLogs(JsonCommand):
"""Get clean logs command."""

_targets_bot: bool = False
name = "GetCleanLogs"
NAME = "GetCleanLogs"

def __init__(self, count: int = 0) -> None:
super().__init__({"count": count})
Expand All @@ -32,7 +32,7 @@ async def _execute_api_request(
self, authenticator: Authenticator, device_info: ApiDeviceInfo
) -> dict[str, Any]:
json = {
"td": self.name,
"td": self.NAME,
"did": device_info["did"],
"resource": device_info["resource"],
}
Expand Down
6 changes: 3 additions & 3 deletions deebot_client/commands/json/clean_preference.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,12 @@
class GetCleanPreference(GetEnableCommand):
"""Get clean preference command."""

name = "getCleanPreference"
event_type = CleanPreferenceEvent
NAME = "getCleanPreference"
EVENT_TYPE = CleanPreferenceEvent


class SetCleanPreference(SetEnableCommand):
"""Set clean preference command."""

name = "setCleanPreference"
NAME = "setCleanPreference"
get_command = GetCleanPreference
Loading

0 comments on commit b5d05a1

Please sign in to comment.