-
Notifications
You must be signed in to change notification settings - Fork 41
Commit
* Add models for RenaultClient * Update fixtures * Use marshmallow_dataclass * Update fixtures * Update fixtures * Update fixtures * Update fixtures * Add KamereonVehicleDataResponse * Add tests for vehicle actions * Add tests for vehicle errors * Fix tests * Add KamereonException * Fix tests * Update parsing of Kamereon errors * Add raw_data to Kamereon models * Fix pre-commit * Fix method descriptions * Remove attributes property on KamereonVehicleData model
- Loading branch information
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,11 +1,27 @@ | ||
"""Models for Renault API.""" | ||
from dataclasses import dataclass | ||
from typing import Any | ||
from typing import Dict | ||
|
||
import marshmallow | ||
|
||
|
||
@dataclass | ||
class BaseModel: | ||
"""Base model for Gigya and Kamereon models to include raw_data.""" | ||
|
||
raw_data: Dict[str, Any] | ||
|
||
|
||
class BaseSchema(marshmallow.Schema): | ||
"""Base schema for Gigya models to exclude unknown fields.""" | ||
"""Base schema for Gigya and Kamereon models to exclude unknown fields.""" | ||
|
||
class Meta: | ||
"""Force unknown fields to 'exclude'.""" | ||
|
||
unknown = marshmallow.EXCLUDE | ||
|
||
@marshmallow.pre_load | ||
def get_raw_data(self, data, **kwargs): # type: ignore | ||
"""Ensure raw_data is added to the data set.""" | ||
return {"raw_data": data, **data} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,117 @@ | ||
"""Kamereon models.""" | ||
import json | ||
from dataclasses import dataclass | ||
from typing import List | ||
from typing import Optional | ||
|
||
import marshmallow_dataclass | ||
|
||
from . import BaseModel | ||
from . import BaseSchema | ||
from renault_api.exceptions import KamereonResponseException | ||
|
||
|
||
@dataclass | ||
class KamereonResponseError(BaseModel): | ||
"""Kamereon response error.""" | ||
|
||
errorCode: Optional[str] # noqa: N815 | ||
errorMessage: Optional[str] # noqa: N815 | ||
|
||
def raise_for_error_code(self) -> None: | ||
"""Raise exception from response error.""" | ||
raise KamereonResponseException(self.errorCode, self.get_error_details()) | ||
|
||
def get_error_details(self) -> Optional[str]: | ||
"""Extract the error details sometimes hidden inside nested JSON.""" | ||
try: | ||
error_details = json.loads(self.errorMessage or "{}") | ||
except json.JSONDecodeError: | ||
return self.errorMessage | ||
|
||
error_descriptions = [] | ||
for inner_error in error_details.get("errors", []): | ||
error_description = " ".join( | ||
filter( | ||
None, | ||
[ | ||
inner_error.get("title"), | ||
inner_error.get("source", {}).get("pointer"), | ||
inner_error.get("detail"), | ||
], | ||
) | ||
) | ||
error_descriptions.append(error_description) | ||
|
||
return ", ".join(error_descriptions) or self.errorMessage | ||
|
||
|
||
@dataclass | ||
class KamereonResponse(BaseModel): | ||
"""Kamereon response.""" | ||
|
||
errors: Optional[List[KamereonResponseError]] | ||
|
||
def raise_for_error_code(self) -> None: | ||
"""Raise exception if errors found in the response.""" | ||
for error in self.errors or []: | ||
# Until we have a sample for multiple errors, just raise on first one | ||
error.raise_for_error_code() | ||
|
||
|
||
@dataclass | ||
class KamereonPersonAccount(BaseModel): | ||
"""Kamereon account data.""" | ||
|
||
accountId: Optional[str] # noqa: N815 | ||
accountType: Optional[str] # noqa: N815 | ||
accountStatus: Optional[str] # noqa: N815 | ||
|
||
|
||
@dataclass | ||
class KamereonPersonResponse(KamereonResponse): | ||
"""Kamereon response to GET on /persons/{gigya_person_id}.""" | ||
|
||
accounts: List[KamereonPersonAccount] | ||
|
||
|
||
@dataclass | ||
class KamereonVehiclesLink(BaseModel): | ||
"""Kamereon account data.""" | ||
|
||
vin: Optional[str] | ||
|
||
|
||
@dataclass | ||
class KamereonVehiclesResponse(KamereonResponse): | ||
"""Kamereon response to GET on /accounts/{account_id}/vehicles.""" | ||
|
||
accountId: Optional[str] # noqa: N815 | ||
country: Optional[str] | ||
vehicleLinks: List[KamereonVehiclesLink] # noqa: N815 | ||
|
||
|
||
@dataclass | ||
class KamereonVehicleData(BaseModel): | ||
"""Kamereon account data.""" | ||
|
||
type: Optional[str] | ||
id: Optional[str] | ||
|
||
|
||
@dataclass | ||
class KamereonVehicleDataResponse(KamereonResponse): | ||
"""Kamereon response to GET/POST on .../cars/{vin}/{type}.""" | ||
|
||
data: Optional[KamereonVehicleData] | ||
|
||
|
||
KamereonPersonResponseSchema = marshmallow_dataclass.class_schema( | ||
KamereonPersonResponse, base_schema=BaseSchema | ||
)() | ||
KamereonVehiclesResponseSchema = marshmallow_dataclass.class_schema( | ||
KamereonVehiclesResponse, base_schema=BaseSchema | ||
)() | ||
KamereonVehicleDataResponseSchema = marshmallow_dataclass.class_schema( | ||
KamereonVehicleDataResponse, base_schema=BaseSchema | ||
)() |
This file was deleted.
This file was deleted.
This file was deleted.
This file was deleted.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
{ | ||
"personId": "person-id-1", | ||
"type": "I", | ||
"country": "FR", | ||
"civility": "1", | ||
"firstName": "firstName", | ||
"lastName": "lastName", | ||
"idp": { | ||
"idpId": "idpId", | ||
"idpType": "GIGYA", | ||
"idpStatus": "ACTIVE", | ||
"login": "email@email.com", | ||
"loginType": "EMAIL", | ||
"lastLoginDate": "2020-11-16T11:43:52Z", | ||
"termsConditionAcceptance": true, | ||
"termsConditionLastAcceptanceDate": "2019-04-29T20:39:37.153608Z" | ||
}, | ||
"emails": [ | ||
{ | ||
"emailType": "MAIN", | ||
"emailValue": "email@email.com", | ||
"validityFlag": true, | ||
"createdDate": "2019-04-29T20:39:37.162651Z", | ||
"lastModifiedDate": "2019-04-29T20:39:37.162654Z", | ||
"functionalCreationDate": "2019-04-29T20:39:37.162651Z", | ||
"functionalModificationDate": "2019-04-29T20:39:37.162654Z" | ||
} | ||
], | ||
"phones": [ | ||
{ | ||
"phoneType": "MOBILE", | ||
"phoneValue": "phoneValue", | ||
"areaCode": "33", | ||
"createdDate": "2019-06-17T09:47:14.745555Z", | ||
"lastModifiedDate": "2019-06-17T09:47:14.745730Z", | ||
"functionalCreationDate": "2019-06-17T09:47:14.745555Z", | ||
"functionalModificationDate": "2019-06-17T09:47:14.745730Z" | ||
} | ||
], | ||
"identities": [], | ||
"myrRequest": false, | ||
"accounts": [ | ||
{ | ||
"accountId": "account-id-1", | ||
"accountType": "MYRENAULT", | ||
"accountStatus": "ACTIVE", | ||
"country": "FR", | ||
"personId": "person-id-1", | ||
"relationType": "OWNER" | ||
}, | ||
{ | ||
"accountId": "account-id-2", | ||
"externalId": "externalId", | ||
"accountType": "SFDC", | ||
"accountStatus": "ACTIVE", | ||
"country": "FR", | ||
"personId": "person-id-1", | ||
"relationType": "OWNER" | ||
} | ||
], | ||
"partyId": "partyId", | ||
"mdmId": "mdmId", | ||
"createdDate": "2019-04-29T20:39:37.163635Z", | ||
"lastModifiedDate": "2020-11-16T11:43:57.658639Z", | ||
"functionalCreationDate": "2019-04-29T20:39:37.162578Z", | ||
"functionalModificationDate": "2020-11-16T11:29:48.631544Z", | ||
"locale": "fr-FR" | ||
} |
This file was deleted.
This file was deleted.
This file was deleted.
This file was deleted.
This file was deleted.
This file was deleted.
This file was deleted.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
{ | ||
"data": { | ||
"type": "ChargeMode", | ||
"id": "guid", | ||
"attributes": { "action": "schedule_mode" } | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
{ | ||
"data": { | ||
"type": "ChargeSchedule", | ||
"id": "guid", | ||
"attributes": { "schedules": [] } | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
{ | ||
"data": { | ||
"type": "ChargingStart", | ||
"id": "guid", | ||
"attributes": { "action": "start" } | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
{ | ||
"data": { | ||
"type": "HvacStart", | ||
"id": "guid", | ||
"attributes": { "action": "cancel" } | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
{ | ||
"data": { | ||
"type": "HvacStart", | ||
"id": "guid", | ||
"attributes": { "action": "start", "targetTemperature": 21.0 } | ||
} | ||
} |
This file was deleted.
This file was deleted.
This file was deleted.
This file was deleted.
This file was deleted.
This file was deleted.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
{ | ||
"data": { | ||
"type": "Car", | ||
"id": "VF1AAAAA555777999", | ||
"attributes": { | ||
"timestamp": "2020-11-17T09:06:48+01:00", | ||
"batteryLevel": 50, | ||
"batteryAutonomy": 128, | ||
"batteryCapacity": 0, | ||
"batteryAvailableEnergy": 0, | ||
"plugStatus": 0, | ||
"chargingStatus": -1.0 | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
{ | ||
"data": { | ||
"type": "Car", | ||
"id": "VF1AAAAA555777999", | ||
"attributes": { | ||
"timestamp": "2020-11-09T07:41:49+01:00", | ||
"batteryLevel": 34, | ||
"batteryTemperature": 10, | ||
"batteryAutonomy": 88, | ||
"batteryCapacity": 0, | ||
"batteryAvailableEnergy": 0, | ||
"plugStatus": 0, | ||
"chargingStatus": -1.0 | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
{ | ||
"data": { | ||
"type": "Car", | ||
"id": "VF1AAAAA555777999", | ||
"attributes": { | ||
"chargeSummaries": [ | ||
{ | ||
"month": "202011", | ||
"totalChargesNumber": 1, | ||
"totalChargesDuration": 479, | ||
"totalChargesErrors": 0 | ||
} | ||
] | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
{ | ||
"data": { | ||
"type": "Car", | ||
"id": "VF1AAAAA555777999", | ||
"attributes": { | ||
"charges": [ | ||
{ | ||
"chargeStartDate": "2020-11-11T00:31:03Z", | ||
"chargeEndDate": "2020-11-11T08:30:17Z", | ||
"chargeDuration": 479, | ||
"chargeStartBatteryLevel": 15, | ||
"chargeEndBatteryLevel": 74, | ||
"chargeBatteryLevelRecovered": 59, | ||
"chargePower": "slow", | ||
"chargeStartInstantaneousPower": 3100, | ||
"chargeEndStatus": "ok" | ||
} | ||
] | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
{ | ||
"data": { | ||
"type": "Car", | ||
"id": "VF1AAAAA555777999", | ||
"attributes": { "totalMileage": 49114.27 } | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
{ | ||
"data": { | ||
"type": "Car", | ||
"id": "VF1AAAAA555777999", | ||
"attributes": { "externalTemperature": 8.0, "hvacStatus": "off" } | ||
} | ||
} |