Skip to content

Commit

Permalink
Merge pull request #323 from cdce8p/fix-typing
Browse files Browse the repository at this point in the history
Fix and improve typing
  • Loading branch information
rikroe committed Nov 7, 2021
2 parents 6f4eaf1 + a7e714e commit 749ac44
Show file tree
Hide file tree
Showing 13 changed files with 86 additions and 38 deletions.
11 changes: 10 additions & 1 deletion .coveragerc
Original file line number Diff line number Diff line change
@@ -1,2 +1,11 @@
[run]
omit = bimmer_connected/cli.py
omit = bimmer_connected/cli.py

[report]
exclude_lines =
# Re-enable default pragma
pragma: no cover

# Type checking code not executed during pytest runs
if TYPE_CHECKING:
@overload
19 changes: 10 additions & 9 deletions bimmer_connected/account.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,10 @@
import urllib
import json
from threading import Lock
from typing import Callable, List
from typing import Any, Callable, Dict, List
import requests
from requests.exceptions import HTTPError
from requests.models import Response

from bimmer_connected.country_selector import (
Regions,
Expand Down Expand Up @@ -62,9 +63,9 @@ def __init__(self, username: str, password: str, region: Regions, log_responses:
self._log_responses = log_responses
self._retries_on_500_error = retries_on_500_error
#: list of vehicles associated with this account.
self._vehicles = []
self._vehicles = [] # type: list[ConnectedDriveVehicle]
self._lock = Lock()
self._update_listeners = []
self._update_listeners = [] # type: list[Callable[[], Any]]

self._get_vehicles()

Expand Down Expand Up @@ -198,7 +199,7 @@ def _get_oauth_token(self) -> None:
raise ex

@property
def request_header(self):
def request_header(self) -> Dict[str, str]:
"""Generate a header for HTTP requests to the server."""
self._get_oauth_token()
headers = {
Expand All @@ -208,7 +209,7 @@ def request_header(self):
return headers

def send_request(self, url: str, data=None, headers=None, expected_response=200, post=False, allow_redirects=True,
logfilename: str = None, params: dict = None):
logfilename: str = None, params: dict = None) -> Response:
"""Send an http request to the server.
If the http headers are not set, default headers are generated.
Expand Down Expand Up @@ -242,7 +243,7 @@ def send_request(self, url: str, data=None, headers=None, expected_response=200,
return response

def send_request_v2(self, url: str, data=None, headers=None, post=False, allow_redirects=True,
logfilename: str = None, params: dict = None):
logfilename: str = None, params: dict = None) -> Response:
"""Send an http request to the server.
If the http headers are not set, default headers are generated.
Expand Down Expand Up @@ -337,7 +338,7 @@ def region(self) -> str:
"""Get the region."""
return self._region

def _get_vehicles(self):
def _get_vehicles(self) -> None:
"""Retrieve list of vehicle for the account."""
_LOGGER.debug('Getting vehicle list')
self._get_oauth_token()
Expand Down Expand Up @@ -369,7 +370,7 @@ def update_vehicle_states(self) -> None:
for listener in self._update_listeners:
listener()

def add_update_listener(self, listener: Callable) -> None:
def add_update_listener(self, listener: Callable[[], Any]) -> None:
"""Add a listener for state updates."""
self._update_listeners.append(listener)

Expand All @@ -378,7 +379,7 @@ def vehicles(self) -> List[ConnectedDriveVehicle]:
"""Get list of vehicle of this account"""
return self._vehicles

def __str__(self):
def __str__(self) -> str:
"""Use the user name as id for the account class."""
return '{}: {}'.format(self.__class__, self._username)

Expand Down
7 changes: 5 additions & 2 deletions bimmer_connected/all_trips.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
"""Models the all trips of a vehicle."""

import logging
from typing import List
from typing import TYPE_CHECKING, List

from bimmer_connected.const import SERVICE_ALL_TRIPS

if TYPE_CHECKING:
from bimmer_connected.state import VehicleState

_LOGGER = logging.getLogger(__name__)


Expand Down Expand Up @@ -94,7 +97,7 @@ def _func_wrapper(self: 'AllTrips', *args, **kwargs):
class AllTrips: # pylint: disable=too-many-public-methods
"""Models the all trips service of a vehicle."""

def __init__(self, state):
def __init__(self, state: "VehicleState"):
"""Constructor."""
self._state = state

Expand Down
7 changes: 5 additions & 2 deletions bimmer_connected/charging_profile.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
"""Models the charging profiles of a vehicle."""

import logging
from typing import List
from typing import TYPE_CHECKING, List
from enum import Enum

from bimmer_connected.const import SERVICE_CHARGING_PROFILE

if TYPE_CHECKING:
from bimmer_connected.state import VehicleState

_LOGGER = logging.getLogger(__name__)


Expand Down Expand Up @@ -92,7 +95,7 @@ def _func_wrapper(self: 'ChargingProfile', *args, **kwargs):
class ChargingProfile: # pylint: disable=too-many-public-methods
"""Models the charging profile of a vehicle."""

def __init__(self, state):
def __init__(self, state: "VehicleState"):
"""Constructor."""
self._state = state

Expand Down
7 changes: 5 additions & 2 deletions bimmer_connected/efficiency.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
"""Models the efficiency of a vehicle."""

import logging
from typing import List
from typing import TYPE_CHECKING, List

from bimmer_connected.const import SERVICE_EFFICIENCY

if TYPE_CHECKING:
from bimmer_connected.state import VehicleState

_LOGGER = logging.getLogger(__name__)


Expand Down Expand Up @@ -116,7 +119,7 @@ def _func_wrapper(self: 'Efficiency', *args, **kwargs):
class Efficiency: # pylint: disable=too-many-public-methods
"""Models the navigation of a vehicle."""

def __init__(self, state):
def __init__(self, state: "VehicleState"):
"""Constructor."""
self._state = state

Expand Down
7 changes: 5 additions & 2 deletions bimmer_connected/last_destinations.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
"""Models the last destinations of a vehicle."""

import logging
from typing import List
from typing import TYPE_CHECKING, List
from enum import Enum

from bimmer_connected.const import SERVICE_DESTINATIONS

if TYPE_CHECKING:
from bimmer_connected.state import VehicleState

_LOGGER = logging.getLogger(__name__)


Expand Down Expand Up @@ -78,7 +81,7 @@ def _func_wrapper(self: 'LastDestinations', *args, **kwargs):
class LastDestinations: # pylint: disable=too-many-public-methods
"""Models the last destinations of a vehicle."""

def __init__(self, state):
def __init__(self, state: "VehicleState"):
"""Constructor."""
self._state = state

Expand Down
7 changes: 5 additions & 2 deletions bimmer_connected/last_trip.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
"""Models the last trip of a vehicle."""

import logging
from typing import List
from typing import TYPE_CHECKING, List

from bimmer_connected.const import SERVICE_LAST_TRIP

if TYPE_CHECKING:
from bimmer_connected.state import VehicleState

_LOGGER = logging.getLogger(__name__)


Expand All @@ -28,7 +31,7 @@ def _func_wrapper(self: 'LastTrip', *args, **kwargs):
class LastTrip: # pylint: disable=too-many-public-methods
"""Models the last trip of a vehicle."""

def __init__(self, state):
def __init__(self, state: "VehicleState"):
"""Constructor."""
self._state = state

Expand Down
6 changes: 5 additions & 1 deletion bimmer_connected/navigation.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
"""Models the navigation of a vehicle."""

import logging
from typing import TYPE_CHECKING

from bimmer_connected.const import SERVICE_NAVIGATION

if TYPE_CHECKING:
from bimmer_connected.state import VehicleState

_LOGGER = logging.getLogger(__name__)


Expand All @@ -27,7 +31,7 @@ def _func_wrapper(self: 'Navigation', *args, **kwargs):
class Navigation: # pylint: disable=too-many-public-methods
"""Models the navigation of a vehicle."""

def __init__(self, state):
def __init__(self, state: "VehicleState"):
"""Constructor."""
self._state = state

Expand Down
7 changes: 5 additions & 2 deletions bimmer_connected/range_maps.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
"""Models the range maps of a vehicle."""

import logging
from typing import List
from typing import TYPE_CHECKING, List
from enum import Enum

from bimmer_connected.const import SERVICE_RANGEMAP

if TYPE_CHECKING:
from bimmer_connected.state import VehicleState

_LOGGER = logging.getLogger(__name__)


Expand Down Expand Up @@ -87,7 +90,7 @@ def _func_wrapper(self: 'RangeMaps', *args, **kwargs):
class RangeMaps: # pylint: disable=too-many-public-methods
"""Models the range maps of a vehicle."""

def __init__(self, state):
def __init__(self, state: "VehicleState"):
"""Constructor."""
self._state = state

Expand Down
14 changes: 10 additions & 4 deletions bimmer_connected/remote_services.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
from json.decoder import JSONDecodeError
import logging
import time
from typing import List
from typing import TYPE_CHECKING, List, TypeVar
from enum import Enum
from urllib.parse import urlencode

Expand All @@ -18,6 +18,10 @@
VEHICLE_POI_URL,
VEHICLE_EADRAX_POI_URL)

if TYPE_CHECKING:
from bimmer_connected.account import ConnectedDriveAccount
from bimmer_connected.vehicle import ConnectedDriveVehicle

TIME_FORMAT = '%Y-%m-%dT%H:%M:%S.%f'

_LOGGER = logging.getLogger(__name__)
Expand All @@ -31,6 +35,8 @@
#: time in seconds to wait before updating the vehicle state from the server
_UPDATE_AFTER_REMOTE_SERVICE_DELAY = 10

TMessage = TypeVar("TMessage", bound="Message")


class ExecutionState(Enum):
"""Enumeration of possible states of the execution of a remote service."""
Expand Down Expand Up @@ -95,12 +101,12 @@ class Message:
"""Text message or PointOfInterst to be sent to the vehicle."""

@classmethod
def from_poi(cls, poi: PointOfInterest):
def from_poi(cls: TMessage, poi: PointOfInterest) -> TMessage:
"""Create a message from a PointOfInterest"""
return cls(poi.__dict__)

@classmethod
def from_text(cls, text: str, subject: str = None):
def from_text(cls: TMessage, text: str, subject: str = None) -> TMessage:
"""Create a text message"""
return cls({"name": subject, "additionalInfo": text[:255]})

Expand Down Expand Up @@ -142,7 +148,7 @@ def _parse_timestamp(timestamp: str) -> datetime.datetime:
class RemoteServices:
"""Trigger remote services on a vehicle."""

def __init__(self, account, vehicle):
def __init__(self, account: "ConnectedDriveAccount", vehicle: "ConnectedDriveVehicle"):
"""Constructor."""
self._account = account
self._vehicle = vehicle
Expand Down
10 changes: 7 additions & 3 deletions bimmer_connected/state.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import logging
import datetime
from typing import List, Tuple
from typing import TYPE_CHECKING, List, Tuple

from bimmer_connected.const import SERVICE_STATUS, VEHICLE_STATUS_URL, SERVICE_LAST_TRIP, \
VEHICLE_STATISTICS_LAST_TRIP_URL, SERVICE_ALL_TRIPS, VEHICLE_STATISTICS_ALL_TRIPS_URL, \
Expand All @@ -20,6 +20,10 @@
from bimmer_connected.navigation import Navigation
from bimmer_connected.efficiency import Efficiency

if TYPE_CHECKING:
from bimmer_connected.account import ConnectedDriveAccount
from bimmer_connected.vehicle import ConnectedDriveVehicle

_LOGGER = logging.getLogger(__name__)


Expand All @@ -46,11 +50,11 @@ class VehicleState:
# pylint: disable=too-many-public-methods
# pylint: disable=too-many-instance-attributes
# Nine is reasonable in this case.
def __init__(self, account, vehicle):
def __init__(self, account: "ConnectedDriveAccount", vehicle: "ConnectedDriveVehicle"):
"""Constructor."""
self._account = account
self._vehicle = vehicle
self._attributes = {}
self._attributes = {} # type: dict[str, dict]
self.vehicle_status = VehicleStatus(self)
self.all_trips = AllTrips(self)
self.charging_profile = ChargingProfile(self)
Expand Down
9 changes: 6 additions & 3 deletions bimmer_connected/vehicle.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
"""Models state and remote services of one vehicle."""
from enum import Enum
import logging
from typing import List
from typing import TYPE_CHECKING, List

from bimmer_connected.state import VehicleState
from bimmer_connected.vehicle_status import WINDOWS, LIDS
Expand All @@ -11,6 +11,9 @@
SERVICE_DESTINATIONS, SERVICE_EFFICIENCY, SERVICE_LAST_TRIP, SERVICE_NAVIGATION, \
SERVICE_RANGEMAP, SERVICE_STATUS

if TYPE_CHECKING:
from bimmer_connected.account import ConnectedDriveAccount

_LOGGER = logging.getLogger(__name__)


Expand Down Expand Up @@ -66,7 +69,7 @@ class ConnectedDriveVehicle:
:param attributes: attributes of the vehicle as provided by the server
"""

def __init__(self, account, attributes: dict) -> None:
def __init__(self, account: "ConnectedDriveAccount", attributes: dict) -> None:
self._account = account
self.attributes = attributes
self.state = VehicleState(account, self)
Expand Down Expand Up @@ -189,7 +192,7 @@ def available_attributes(self) -> List[str]:
return result

@property
def available_state_services(self) -> List:
def available_state_services(self) -> List[str]:
"""Get the list of all available state services for this vehicle."""
result = [SERVICE_STATUS]
if self.has_statistics_service:
Expand Down
Loading

0 comments on commit 749ac44

Please sign in to comment.