Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add lock and unlock functions #190

Merged
merged 12 commits into from
Nov 5, 2022
Merged
3 changes: 3 additions & 0 deletions mytoyota/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
from __future__ import annotations

import asyncio
from http import HTTPStatus
import json
import logging
from typing import Any
Expand Down Expand Up @@ -553,6 +554,7 @@ async def set_lock_vehicle(self, vin: str) -> VehicleLockUnlockActionResponse:

Raises:
ToyotaLoginError: An error returned when updating token or invalid login information.
ToyotaActionNotSupported: The lock action is not supported on this vehicle.
ToyotaInternalError: An error occurred when making a request.
ToyotaApiError: Toyota's API returned an error.
"""
Expand All @@ -570,6 +572,7 @@ async def set_unlock_vehicle(self, vin: str) -> VehicleLockUnlockActionResponse:

Raises:
ToyotaLoginError: An error returned when updating token or invalid login information.
ToyotaActionNotSupported: The lock action is not supported on this vehicle.
ToyotaInternalError: An error occurred when making a request.
ToyotaApiError: Toyota's API returned an error.
"""
Expand Down
9 changes: 8 additions & 1 deletion mytoyota/controller.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,12 @@
TOKEN_VALID_URL,
UUID,
)
from mytoyota.exceptions import ToyotaApiError, ToyotaInternalError, ToyotaLoginError
from mytoyota.exceptions import (
ToyotaApiError,
ToyotaInternalError,
ToyotaLoginError,
ToyotaActionNotSupported,
)
from mytoyota.utils.logs import censor_dict
from mytoyota.utils.token import is_valid_token

Expand Down Expand Up @@ -229,6 +234,8 @@ async def request( # pylint: disable=too-many-branches
raise ToyotaApiError("Servers are overloaded, try again later")
elif response.status_code == HTTPStatus.SERVICE_UNAVAILABLE:
raise ToyotaApiError("Servers are temporarily unavailable")
elif response.status_code == HTTPStatus.FORBIDDEN:
raise ToyotaActionNotSupported("Action is not supported on this vehicle")
joro75 marked this conversation as resolved.
Show resolved Hide resolved
else:
raise ToyotaApiError(
"HTTP: " + str(response.status_code) + " - " + response.text
Expand Down
3 changes: 3 additions & 0 deletions mytoyota/exceptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,3 +27,6 @@ class ToyotaApiError(Exception):

class ToyotaInternalError(Exception):
"""Raise if an internal server error occurres from Toyota."""

class ToyotaActionNotSupported(Exception):
"""Raise if an action is not supported on a vehicle."""
53 changes: 38 additions & 15 deletions tests/test_lock_unlock.py
Original file line number Diff line number Diff line change
@@ -1,16 +1,20 @@
"""pytest tests for mytoyota.client.MyT sending lock/unlock requests"""
import asyncio
from datetime import datetime
import pytest

from mytoyota.models.lock_unlock import VehicleLockUnlockActionResponse
from mytoyota.models.lock_unlock import (
VehicleLockUnlockActionResponse,
VehicleLockUnlockStatusResponse,
)
from mytoyota.exceptions import ToyotaActionNotSupported
from tests.test_myt import TestMyTHelper


class TestLockUnlock(TestMyTHelper):
"""Pytest functions to test locking and unlocking"""

def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.lock_request_id = "d4f873d2-5da2-494f-a6d9-6e56d18d2ce9"
_lock_request_id = "d4f873d2-5da2-494f-a6d9-6e56d18d2ce9"

def test_send_lock_request(self):
"""Test sending the lock request"""
Expand All @@ -20,12 +24,12 @@ def test_send_lock_request(self):
myt.set_lock_vehicle(vehicle["vin"])
)
assert isinstance(result, VehicleLockUnlockActionResponse)
assert result == {
"id": self.lock_request_id,
assert result.raw_json == {
"id": self._lock_request_id,
"status": "inprogress",
"type": "controlLock",
}
assert result.request_id == self.lock_request_id
assert result.request_id == self._lock_request_id
assert result.status == "inprogress"
assert result.type == "controlLock"

Expand All @@ -37,8 +41,8 @@ def test_send_unlock_request(self):
myt.set_unlock_vehicle(vehicle["vin"])
)
assert isinstance(result, VehicleLockUnlockActionResponse)
assert result == {
"id": self.lock_request_id,
assert result.raw_json == {
"id": self._lock_request_id,
"status": "inprogress",
"type": "controlLock",
}
Expand All @@ -48,16 +52,35 @@ def test_get_lock_status(self):
myt = self._create_offline_myt()
vehicle = self._lookup_vehicle(myt, 4444444)
result = asyncio.get_event_loop().run_until_complete(
myt.get_lock_status(vehicle["vin"], self.lock_request_id)
myt.get_lock_status(vehicle["vin"], self._lock_request_id)
)
assert isinstance(result, VehicleLockUnlockActionResponse)
assert result == {
"id": self.lock_request_id,
assert isinstance(result, VehicleLockUnlockStatusResponse)
assert result.raw_json == {
"id": self._lock_request_id,
"status": "completed",
"requestTimestamp": "2022-10-22T08:49:20.071Z",
"type": "controlLock",
}
assert result.request_id == self.lock_request_id
assert result.request_id == self._lock_request_id
assert result.status == "completed"
assert result.type == "controlLock"
assert result.request_timestamp == "2022-10-22T08:49:20.071Z"
assert result.request_timestamp == datetime(2022, 10, 22, 8, 49, 20, 71000)

def test_set_lock_vehicle_unsupported(self):
"""Test sending the lock request to a vehicle for which it is not supported"""
myt = self._create_offline_myt()
vehicle = self._lookup_vehicle(myt, 1111111)
with pytest.raises(ToyotaActionNotSupported):
result = asyncio.get_event_loop().run_until_complete(
myt.set_lock_vehicle(vehicle["vin"])
)

def test_set_unlock_vehicle_unsupported(self):
"""Test sending the lock request to a vehicle for which it is not supported"""
myt = self._create_offline_myt()
vehicle = self._lookup_vehicle(myt, 1111111)
with pytest.raises(ToyotaActionNotSupported):
result = asyncio.get_event_loop().run_until_complete(
myt.set_unlock_vehicle(vehicle["vin"])
)

10 changes: 7 additions & 3 deletions tests/test_myt.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
ToyotaInvalidUsername,
ToyotaLocaleNotValid,
ToyotaRegionNotSupported,
ToyotaActionNotSupported,
)
from mytoyota.models.trip import DetailedTrip, Trip, TripEvent

Expand Down Expand Up @@ -148,9 +149,12 @@ async def request( # pylint: disable=R0915;
match = re.match(r".*/vehicles/([^?]+)/lock", endpoint)
if match:
vin = match.group(1)
response = self._load_from_file(
os.path.join(data_files, f"vehicle_{vin}_lock_request.json")
)
try:
response = self._load_from_file(
os.path.join(data_files, f"vehicle_{vin}_lock_request.json")
)
except FileNotFoundError:
raise ToyotaActionNotSupported("Action is not supported")

match = re.match(r".*/vehicles/([^?]+)/lock/([^?]+)", endpoint)
if match:
Expand Down