From 812aa5a7811ec4d75c71818b1b4ee31a496755d0 Mon Sep 17 00:00:00 2001 From: Richard Kroegel <42204099+rikroe@users.noreply.github.com> Date: Sat, 27 Jul 2024 15:14:27 +0200 Subject: [PATCH] Fixes for HA mypy, add more lint rules (#639) * Update MyPy for HA * Add more rules to ruff --- bimmer_connected/cli.py | 11 +-- bimmer_connected/models.py | 6 +- bimmer_connected/tests/test_account.py | 44 ++++----- bimmer_connected/tests/test_api.py | 2 +- bimmer_connected/tests/test_cli.py | 9 +- .../tests/test_remote_services.py | 24 ++--- bimmer_connected/tests/test_utils.py | 8 +- bimmer_connected/tests/test_vehicle.py | 22 ++--- bimmer_connected/tests/test_vehicle_status.py | 90 +++++++++---------- bimmer_connected/utils.py | 7 +- bimmer_connected/vehicle/fuel_and_battery.py | 17 ++-- bimmer_connected/vehicle/remote_services.py | 2 +- pyproject.toml | 9 +- 13 files changed, 120 insertions(+), 131 deletions(-) diff --git a/bimmer_connected/cli.py b/bimmer_connected/cli.py index 204d5a39..3b7b94bf 100644 --- a/bimmer_connected/cli.py +++ b/bimmer_connected/cli.py @@ -3,6 +3,7 @@ import argparse import asyncio +import contextlib import json import logging import sys @@ -250,10 +251,8 @@ async def image(account: MyBMWAccount, args) -> None: for viewdirection in VehicleViewDirection: if viewdirection == VehicleViewDirection.UNKNOWN: continue - filename = str(viewdirection.name).lower() + ".png" - with open(filename, "wb") as output_file: - image_data = await vehicle.get_vehicle_image(viewdirection) - output_file.write(image_data) + filename = (Path.cwd() / str(viewdirection.name).lower()).with_suffix(".png") + await asyncio.to_thread(filename.write_bytes, await vehicle.get_vehicle_image(viewdirection)) print(f"vehicle image saved to {filename}") @@ -336,10 +335,8 @@ def main(): account.set_observer_position(args.lat, args.lng) if args.oauth_store.exists(): - try: + with contextlib.suppress(json.JSONDecodeError): account.set_refresh_token(**json.loads(args.oauth_store.read_text())) - except json.JSONDecodeError: - pass loop = asyncio.get_event_loop() try: diff --git a/bimmer_connected/models.py b/bimmer_connected/models.py index a45d33b6..4a6adaf6 100644 --- a/bimmer_connected/models.py +++ b/bimmer_connected/models.py @@ -23,7 +23,7 @@ def _missing_(cls, value): return member if has_unknown: _LOGGER.warning("'%s' is not a valid '%s'", value, cls.__name__) - return getattr(cls, "UNKNOWN") + return cls.UNKNOWN raise ValueError(f"'{value}' is not a valid {cls.__name__}") @@ -117,7 +117,7 @@ class PointOfInterest: lat: InitVar[float] lon: InitVar[float] - name: InitVar[str] = DEFAULT_POI_NAME + name: InitVar[Optional[str]] = DEFAULT_POI_NAME street: InitVar[str] = None postal_code: InitVar[str] = None city: InitVar[str] = None @@ -130,7 +130,7 @@ class PointOfInterest: entrances: Optional[List] = field(init=False) placeType: Optional[str] = "ADDRESS" category: Dict[str, Optional[str]] = field(init=False) - title: str = "Sent with ♥ by bimmer_connected" + title: Optional[str] = DEFAULT_POI_NAME # The following attributes are not by us but available in the API provider: Optional[str] = None diff --git a/bimmer_connected/tests/test_account.py b/bimmer_connected/tests/test_account.py index 3f888dd7..7ebd7fab 100644 --- a/bimmer_connected/tests/test_account.py +++ b/bimmer_connected/tests/test_account.py @@ -180,7 +180,7 @@ async def test_vehicles(bmw_fixture: respx.Router): vehicle = account.get_vehicle(VIN_G26) assert vehicle is not None - assert VIN_G26 == vehicle.vin + assert vehicle.vin == VIN_G26 assert account.get_vehicle("invalid_vin") is None @@ -425,9 +425,8 @@ async def test_429_retry_raise_login(caplog, bmw_fixture: respx.Router): bmw_fixture.get("/eadrax-ucs/v1/presentation/oauth/config").mock(return_value=httpx.Response(429, json=json_429)) caplog.set_level(logging.DEBUG) - with mock.patch("asyncio.sleep", new_callable=mock.AsyncMock): - with pytest.raises(MyBMWAPIError): - await account.get_vehicles() + with mock.patch("asyncio.sleep", new_callable=mock.AsyncMock), pytest.raises(MyBMWAPIError): + await account.get_vehicles() log_429 = [ r @@ -477,9 +476,8 @@ async def test_429_retry_raise_vehicles(caplog, bmw_fixture: respx.Router): bmw_fixture.post(VEHICLES_URL).mock(return_value=httpx.Response(429, json=json_429)) caplog.set_level(logging.DEBUG) - with mock.patch("asyncio.sleep", new_callable=mock.AsyncMock): - with pytest.raises(MyBMWQuotaError): - await account.get_vehicles() + with mock.patch("asyncio.sleep", new_callable=mock.AsyncMock), pytest.raises(MyBMWQuotaError): + await account.get_vehicles() log_429 = [ r @@ -530,9 +528,8 @@ async def test_429_retry_with_login_raise_vehicles(bmw_fixture: respx.Router): ] ) - with mock.patch("asyncio.sleep", new_callable=mock.AsyncMock): - with pytest.raises(MyBMWQuotaError): - await account.get_vehicles() + with mock.patch("asyncio.sleep", new_callable=mock.AsyncMock), pytest.raises(MyBMWQuotaError): + await account.get_vehicles() @pytest.mark.asyncio @@ -547,9 +544,8 @@ async def test_multiple_401(bmw_fixture: respx.Router): ] ) - with mock.patch("asyncio.sleep", new_callable=mock.AsyncMock): - with pytest.raises(MyBMWAuthError): - await account.get_vehicles() + with mock.patch("asyncio.sleep", new_callable=mock.AsyncMock), pytest.raises(MyBMWAuthError): + await account.get_vehicles() @pytest.mark.asyncio @@ -594,9 +590,8 @@ async def test_401_after_429_fail(bmw_fixture: respx.Router): ] ) - with mock.patch("asyncio.sleep", new_callable=mock.AsyncMock): - with pytest.raises(MyBMWQuotaError): - await account.get_vehicles() + with mock.patch("asyncio.sleep", new_callable=mock.AsyncMock), pytest.raises(MyBMWQuotaError): + await account.get_vehicles() @pytest.mark.asyncio @@ -614,9 +609,8 @@ async def test_403_quota_exceeded_vehicles_usa(caplog, bmw_fixture: respx.Router ) caplog.set_level(logging.DEBUG) - with mock.patch("asyncio.sleep", new_callable=mock.AsyncMock): - with pytest.raises(MyBMWQuotaError): - await account.get_vehicles() + with mock.patch("asyncio.sleep", new_callable=mock.AsyncMock), pytest.raises(MyBMWQuotaError): + await account.get_vehicles() log_quota = [r for r in caplog.records if "quota" in r.message] assert len(log_quota) == 1 @@ -671,13 +665,13 @@ async def test_no_vehicle_details(caplog, bmw_fixture: respx.Router): async def test_client_async_only(bmw_fixture: respx.Router): """Test that the Authentication providers only work async.""" - with httpx.Client(auth=MyBMWAuthentication(TEST_USERNAME, TEST_PASSWORD, TEST_REGION)) as client: - with pytest.raises(RuntimeError): - client.get("/eadrax-ucs/v1/presentation/oauth/config") + with httpx.Client(auth=MyBMWAuthentication(TEST_USERNAME, TEST_PASSWORD, TEST_REGION)) as client, pytest.raises( + RuntimeError + ): + client.get("/eadrax-ucs/v1/presentation/oauth/config") - with httpx.Client(auth=MyBMWLoginRetry()) as client: - with pytest.raises(RuntimeError): - client.get("/eadrax-ucs/v1/presentation/oauth/config") + with httpx.Client(auth=MyBMWLoginRetry()) as client, pytest.raises(RuntimeError): + client.get("/eadrax-ucs/v1/presentation/oauth/config") @pytest.mark.asyncio diff --git a/bimmer_connected/tests/test_api.py b/bimmer_connected/tests/test_api.py index beb074df..24903493 100644 --- a/bimmer_connected/tests/test_api.py +++ b/bimmer_connected/tests/test_api.py @@ -25,7 +25,7 @@ def test_valid_regions(): """Test valid regions.""" - assert ["north_america", "china", "rest_of_world"] == valid_regions() + assert valid_regions() == ["north_america", "china", "rest_of_world"] def test_unknown_region(): diff --git a/bimmer_connected/tests/test_cli.py b/bimmer_connected/tests/test_cli.py index b0c33982..ebe0cef1 100644 --- a/bimmer_connected/tests/test_cli.py +++ b/bimmer_connected/tests/test_cli.py @@ -1,3 +1,4 @@ +import contextlib import json import subprocess import sys @@ -48,10 +49,8 @@ def test_status_json_filtered(capsys: pytest.CaptureFixture, vin, expected_count """Test the status command JSON output filtered by VIN.""" sys.argv = ["bimmerconnected", "status", "-j", "-v", vin, *ARGS_USER_PW_REGION] - try: + with contextlib.suppress(SystemExit): bimmer_connected.cli.main() - except SystemExit: - pass result = capsys.readouterr() if expected_count == 1: @@ -90,10 +89,8 @@ def test_status_filtered(capsys: pytest.CaptureFixture, vin, expected_count): """Test the status command text output filtered by VIN.""" sys.argv = ["bimmerconnected", "status", "-v", vin, *ARGS_USER_PW_REGION] - try: + with contextlib.suppress(SystemExit): bimmer_connected.cli.main() - except SystemExit: - pass result = capsys.readouterr() assert f"Found {get_fingerprint_count('states')} vehicles" in result.out diff --git a/bimmer_connected/tests/test_remote_services.py b/bimmer_connected/tests/test_remote_services.py index 79b0fa4e..494931b8 100644 --- a/bimmer_connected/tests/test_remote_services.py +++ b/bimmer_connected/tests/test_remote_services.py @@ -41,13 +41,13 @@ def test_states(): """Test parsing the different response types.""" rss = RemoteServiceStatus(load_response(REMOTE_SERVICE_RESPONSE_PENDING)) - assert ExecutionState.PENDING == rss.state + assert rss.state == ExecutionState.PENDING rss = RemoteServiceStatus(load_response(REMOTE_SERVICE_RESPONSE_DELIVERED)) - assert ExecutionState.DELIVERED == rss.state + assert rss.state == ExecutionState.DELIVERED rss = RemoteServiceStatus(load_response(REMOTE_SERVICE_RESPONSE_EXECUTED)) - assert ExecutionState.EXECUTED == rss.state + assert rss.state == ExecutionState.EXECUTED ALL_SERVICES = { @@ -82,7 +82,7 @@ async def test_trigger_remote_services(bmw_fixture: respx.Router): response = await getattr(vehicle.remote_services, service["call"])( # type: ignore[call-overload] *service.get("args", []), **service.get("kwargs", {}) ) - assert ExecutionState.EXECUTED == response.state + assert response.state == ExecutionState.EXECUTED if service["refresh"]: mock_listener.assert_called_once_with() @@ -309,18 +309,18 @@ async def test_get_remote_position(bmw_fixture: respx.Router): location = vehicle.vehicle_location # Check original position - assert (48.177334, 11.556274) == location.location - assert 180 == location.heading + assert location.location == (48.177334, 11.556274) + assert location.heading == 180 # Check updated position await vehicle.remote_services.trigger_remote_vehicle_finder() - assert (123.456, 34.5678) == location.location - assert 121 == location.heading + assert location.location == (123.456, 34.5678) + assert location.heading == 121 # Position should still be from vehicle finder after status update await account.get_vehicles() - assert (123.456, 34.5678) == location.location - assert 121 == location.heading + assert location.location == (123.456, 34.5678) + assert location.heading == 121 @pytest.mark.asyncio @@ -364,8 +364,8 @@ async def test_get_remote_position_too_old(bmw_fixture: respx.Router): await vehicle.remote_services.trigger_remote_vehicle_finder() - assert (48.177334, 11.556274) == location.location - assert 180 == location.heading + assert location.location == (48.177334, 11.556274) + assert location.heading == 180 @pytest.mark.asyncio diff --git a/bimmer_connected/tests/test_utils.py b/bimmer_connected/tests/test_utils.py index 79397d6b..d8a2ed1b 100644 --- a/bimmer_connected/tests/test_utils.py +++ b/bimmer_connected/tests/test_utils.py @@ -23,7 +23,7 @@ async def test_drive_train(bmw_fixture: respx.Router): """Tests available attribute.""" vehicle = (await prepare_account_with_vehicles()).get_vehicle(VIN_G26) - assert [ + assert get_class_property_names(vehicle) == [ "available_attributes", "brand", "drive_train", @@ -51,7 +51,7 @@ async def test_drive_train(bmw_fixture: respx.Router): "name", "timestamp", "vin", - ] == get_class_property_names(vehicle) + ] def test_parse_datetime(caplog): @@ -89,10 +89,10 @@ def test_json_encoder(): cls=MyBMWJSONEncoder, ) - assert ( + assert encoded == ( '{"datetime": "2022-06-02T22:19:34.123456", "date": "2022-06-02", "value": [17, "mi"],' ' "list": [{"value_int": 1, "value_str": "string"}, "America/Los_Angeles"]}' - ) == encoded + ) def test_charging_settings(): diff --git a/bimmer_connected/tests/test_vehicle.py b/bimmer_connected/tests/test_vehicle.py index 2280b90d..c1f3d53e 100644 --- a/bimmer_connected/tests/test_vehicle.py +++ b/bimmer_connected/tests/test_vehicle.py @@ -46,19 +46,19 @@ async def test_drive_train(caplog, bmw_fixture: respx.Router): """Tests around drive_train attribute.""" account = await prepare_account_with_vehicles() vehicle = account.get_vehicle(VIN_F31) - assert DriveTrainType.COMBUSTION == vehicle.drive_train + assert vehicle.drive_train == DriveTrainType.COMBUSTION vehicle = account.get_vehicle(VIN_G01) - assert DriveTrainType.PLUGIN_HYBRID == vehicle.drive_train + assert vehicle.drive_train == DriveTrainType.PLUGIN_HYBRID vehicle = account.get_vehicle(VIN_G26) - assert DriveTrainType.ELECTRIC == vehicle.drive_train + assert vehicle.drive_train == DriveTrainType.ELECTRIC vehicle = account.get_vehicle(VIN_I01_NOREX) - assert DriveTrainType.ELECTRIC == vehicle.drive_train + assert vehicle.drive_train == DriveTrainType.ELECTRIC vehicle = account.get_vehicle(VIN_I01_REX) - assert DriveTrainType.ELECTRIC_WITH_RANGE_EXTENDER == vehicle.drive_train + assert vehicle.drive_train == DriveTrainType.ELECTRIC_WITH_RANGE_EXTENDER assert len(get_deprecation_warning_count(caplog)) == 0 @@ -145,10 +145,10 @@ async def test_available_attributes(caplog, bmw_fixture: respx.Router): account = await prepare_account_with_vehicles() vehicle = account.get_vehicle(VIN_F31) - assert ["gps_position", "vin"] == vehicle.available_attributes + assert vehicle.available_attributes == ["gps_position", "vin"] vehicle = account.get_vehicle(VIN_G01) - assert [ + assert vehicle.available_attributes == [ "gps_position", "vin", "remaining_range_total", @@ -176,10 +176,10 @@ async def test_available_attributes(caplog, bmw_fixture: respx.Router): "timestamp", "lids", "windows", - ] == vehicle.available_attributes + ] vehicle = account.get_vehicle(VIN_G26) - assert [ + assert vehicle.available_attributes == [ "gps_position", "vin", "remaining_range_total", @@ -204,7 +204,7 @@ async def test_available_attributes(caplog, bmw_fixture: respx.Router): "timestamp", "lids", "windows", - ] == vehicle.available_attributes + ] assert len(get_deprecation_warning_count(caplog)) == 0 @@ -219,7 +219,7 @@ async def test_vehicle_image(caplog, bmw_fixture: respx.Router): params={"carView": "FrontView"}, headers={"accept": "image/png", "bmw-app-vehicle-type": "connected", "bmw-vin": VIN_G01}, ).respond(200, content="png_image") - assert b"png_image" == await vehicle.get_vehicle_image(VehicleViewDirection.FRONT) + assert await vehicle.get_vehicle_image(VehicleViewDirection.FRONT) == b"png_image" assert len(get_deprecation_warning_count(caplog)) == 0 diff --git a/bimmer_connected/tests/test_vehicle_status.py b/bimmer_connected/tests/test_vehicle_status.py index bc3619e5..001e4e82 100644 --- a/bimmer_connected/tests/test_vehicle_status.py +++ b/bimmer_connected/tests/test_vehicle_status.py @@ -42,8 +42,8 @@ async def test_generic(caplog, bmw_fixture: respx.Router): expected = datetime.datetime(year=2023, month=1, day=4, hour=14, minute=57, second=6, tzinfo=UTC) assert expected == status.timestamp - assert 1121 == status.mileage[0] - assert "km" == status.mileage[1] + assert status.mileage[0] == 1121 + assert status.mileage[1] == "km" assert len(get_deprecation_warning_count(caplog)) == 0 @@ -100,14 +100,14 @@ async def test_range_combustion(caplog, bmw_fixture: respx.Router): vehicle = (await prepare_account_with_vehicles()).get_vehicle(VIN_G20) status = vehicle.fuel_and_battery - assert (40, "L") == status.remaining_fuel - assert (629, "km") == status.remaining_range_fuel + assert status.remaining_fuel == (40, "L") + assert status.remaining_range_fuel == (629, "km") assert status.remaining_fuel_percent == 80 assert status.remaining_battery_percent is None assert status.remaining_range_electric == (None, None) - assert (629, "km") == status.remaining_range_total + assert status.remaining_range_total == (629, "km") status_from_vehicle_data = FuelAndBattery.from_vehicle_data(vehicle.data) assert status_from_vehicle_data == status @@ -121,14 +121,14 @@ async def test_range_phev(caplog, bmw_fixture: respx.Router): """Test if the parsing of mileage and range is working.""" status = (await prepare_account_with_vehicles()).get_vehicle(VIN_G01).fuel_and_battery - assert (40, "L") == status.remaining_fuel - assert (436, "km") == status.remaining_range_fuel - assert 80 == status.remaining_fuel_percent + assert status.remaining_fuel == (40, "L") + assert status.remaining_range_fuel == (436, "km") + assert status.remaining_fuel_percent == 80 - assert 80 == status.remaining_battery_percent - assert (40, "km") == status.remaining_range_electric + assert status.remaining_battery_percent == 80 + assert status.remaining_range_electric == (40, "km") - assert (476, "km") == status.remaining_range_total + assert status.remaining_range_total == (476, "km") assert status.remaining_range_fuel[0] + status.remaining_range_electric[0] == status.remaining_range_total[0] @@ -140,14 +140,14 @@ async def test_range_rex(caplog, bmw_fixture: respx.Router): """Test if the parsing of mileage and range is working.""" status = (await prepare_account_with_vehicles()).get_vehicle(VIN_I01_REX).fuel_and_battery - assert (6, "L") == status.remaining_fuel - assert (105, "km") == status.remaining_range_fuel + assert status.remaining_fuel == (6, "L") + assert status.remaining_range_fuel == (105, "km") assert status.remaining_fuel_percent is None - assert 82 == status.remaining_battery_percent - assert (174, "km") == status.remaining_range_electric + assert status.remaining_battery_percent == 82 + assert status.remaining_range_electric == (174, "km") - assert (279, "km") == status.remaining_range_total + assert status.remaining_range_total == (279, "km") assert status.remaining_range_fuel[0] + status.remaining_range_electric[0] == status.remaining_range_total[0] @@ -163,10 +163,10 @@ async def test_range_electric(caplog, bmw_fixture: respx.Router): assert status.remaining_range_fuel == (None, None) assert status.remaining_fuel_percent is None - assert 70 == status.remaining_battery_percent - assert (340, "km") == status.remaining_range_electric + assert status.remaining_battery_percent == 70 + assert status.remaining_range_electric == (340, "km") - assert (340, "km") == status.remaining_range_total + assert status.remaining_range_total == (340, "km") assert len(get_deprecation_warning_count(caplog)) == 0 @@ -213,21 +213,21 @@ async def test_condition_based_services(caplog, bmw_fixture: respx.Router): vehicle = (await prepare_account_with_vehicles()).get_vehicle(VIN_G26) cbs = vehicle.condition_based_services.messages - assert 5 == len(cbs) - assert ConditionBasedServiceStatus.OK == cbs[0].state + assert len(cbs) == 5 + assert cbs[0].state == ConditionBasedServiceStatus.OK expected_cbs0 = datetime.datetime(year=2024, month=12, day=1, tzinfo=UTC) assert expected_cbs0 == cbs[0].due_date - assert (50000, "km") == cbs[0].due_distance + assert cbs[0].due_distance == (50000, "km") - assert ConditionBasedServiceStatus.OK == cbs[1].state + assert cbs[1].state == ConditionBasedServiceStatus.OK expected_cbs1 = datetime.datetime(year=2024, month=12, day=1, tzinfo=UTC) assert expected_cbs1 == cbs[1].due_date - assert (50000, "km") == cbs[1].due_distance + assert cbs[1].due_distance == (50000, "km") - assert ConditionBasedServiceStatus.OK == cbs[2].state + assert cbs[2].state == ConditionBasedServiceStatus.OK expected_cbs2 = datetime.datetime(year=2024, month=12, day=1, tzinfo=UTC) assert expected_cbs2 == cbs[2].due_date - assert (50000, "km") == cbs[2].due_distance + assert cbs[2].due_distance == (50000, "km") assert vehicle.condition_based_services.is_service_required is False @@ -239,8 +239,8 @@ async def test_position_generic(caplog, bmw_fixture: respx.Router): """Test generic attributes.""" status = (await prepare_account_with_vehicles()).get_vehicle(VIN_G26) - assert (48.177334, 11.556274) == status.vehicle_location.location - assert 180 == status.vehicle_location.heading + assert status.vehicle_location.location == (48.177334, 11.556274) + assert status.vehicle_location.heading == 180 assert VehicleLocation.from_vehicle_data(status.data).location == status.vehicle_location.location @@ -293,10 +293,10 @@ async def test_parse_gcj02_position(caplog, bmw_fixture: respx.Router): # Update twice to test against slowly crawling position due to GCJ02 to WGS84 conversion vehicle.update_state(dict(vehicle.data, **vehicle_test_data)) - assert (39.8337, 116.22617) == ( + assert ( round(vehicle.vehicle_location.location[0], 5), round(vehicle.vehicle_location.location[1], 5), - ) + ) == (39.8337, 116.22617) assert len(get_deprecation_warning_count(caplog)) == 0 @@ -313,16 +313,16 @@ async def test_lids(caplog, bmw_fixture: respx.Router): status = (await prepare_account_with_vehicles()).get_vehicle(VIN_G26).doors_and_windows for lid in status.lids: - assert LidState.CLOSED == lid.state + assert lid.state == LidState.CLOSED assert status.all_lids_closed is True - assert 6 == len(list(status.lids)) + assert len(list(status.lids)) == 6 status = (await prepare_account_with_vehicles()).get_vehicle(VIN_I01_REX).doors_and_windows for lid in status.lids: - assert LidState.CLOSED == lid.state + assert lid.state == LidState.CLOSED assert status.all_lids_closed is True - assert 7 == len(list(status.lids)) + assert len(list(status.lids)) == 7 assert status.lids[-1].name == "sunRoof" @@ -335,10 +335,10 @@ async def test_windows_g01(caplog, bmw_fixture: respx.Router): status = (await prepare_account_with_vehicles()).get_vehicle(VIN_G01).doors_and_windows for window in status.windows: - assert LidState.CLOSED == window.state + assert window.state == LidState.CLOSED - assert 5 == len(list(status.windows)) - assert 0 == len(list(status.open_windows)) + assert len(list(status.windows)) == 5 + assert len(list(status.open_windows)) == 0 assert status.all_windows_closed is True assert len(get_deprecation_warning_count(caplog)) == 0 @@ -349,11 +349,11 @@ async def test_door_locks(caplog, bmw_fixture: respx.Router): """Test the door locks.""" status = (await prepare_account_with_vehicles()).get_vehicle(VIN_G01).doors_and_windows - assert LockState.LOCKED == status.door_lock_state + assert status.door_lock_state == LockState.LOCKED status = (await prepare_account_with_vehicles()).get_vehicle(VIN_I01_REX).doors_and_windows - assert LockState.UNLOCKED == status.door_lock_state + assert status.door_lock_state == LockState.UNLOCKED assert len(get_deprecation_warning_count(caplog)) == 0 @@ -369,20 +369,20 @@ async def test_check_control_messages(caplog, bmw_fixture: respx.Router): assert vehicle.check_control_messages.has_check_control_messages is True ccms = vehicle.check_control_messages.messages - assert 2 == len(ccms) + assert len(ccms) == 2 - assert CheckControlStatus.MEDIUM == ccms[1].state - assert "ENGINE_OIL" == ccms[1].description_short + assert ccms[1].state == CheckControlStatus.MEDIUM + assert ccms[1].description_short == "ENGINE_OIL" assert None is ccms[1].description_long vehicle = (await prepare_account_with_vehicles()).get_vehicle(VIN_G20) assert vehicle.check_control_messages.has_check_control_messages is False ccms = vehicle.check_control_messages.messages - assert 2 == len(ccms) + assert len(ccms) == 2 - assert CheckControlStatus.LOW == ccms[1].state - assert "ENGINE_OIL" == ccms[1].description_short + assert ccms[1].state == CheckControlStatus.LOW + assert ccms[1].description_short == "ENGINE_OIL" assert None is ccms[1].description_long assert len(get_deprecation_warning_count(caplog)) == 0 diff --git a/bimmer_connected/utils.py b/bimmer_connected/utils.py index 3db1439f..996ba2f8 100644 --- a/bimmer_connected/utils.py +++ b/bimmer_connected/utils.py @@ -49,11 +49,8 @@ def get_next_occurrence(now: datetime.datetime, time: datetime.time) -> datetime """Get the next occurrence of a given time.""" # If current time is past the given time, add one day to the current date - if now.time() > time: - next_date = now.date() + datetime.timedelta(days=1) - # If current time is before the given time, use the current date - else: - next_date = now.date() + # Otherwise use the current date + next_date = now.date() + datetime.timedelta(days=1) if now.time() > time else now.date() next_occurrence = datetime.datetime.combine(next_date, time) return next_occurrence diff --git a/bimmer_connected/vehicle/fuel_and_battery.py b/bimmer_connected/vehicle/fuel_and_battery.py index dbcc382e..0f3b641a 100644 --- a/bimmer_connected/vehicle/fuel_and_battery.py +++ b/bimmer_connected/vehicle/fuel_and_battery.py @@ -94,15 +94,14 @@ def _parse_vehicle_data(cls, vehicle_data: Dict) -> Optional[Dict]: if drivetrain in COMBUSTION_ENGINE_DRIVE_TRAINS: retval.update(cls._parse_fuel_data(state.get("combustionFuelLevel", {}))) - if drivetrain in HV_BATTERY_DRIVE_TRAINS: - if electric_data := state.get("electricChargingState", {}): - retval.update( - cls._parse_electric_data( - electric_data, - vehicle_data["fetched_at"], - state.get("chargingProfile", {}).get("reductionOfChargeCurrent"), - ), - ) + if drivetrain in HV_BATTERY_DRIVE_TRAINS and (electric_data := state.get("electricChargingState", {})): + retval.update( + cls._parse_electric_data( + electric_data, + vehicle_data["fetched_at"], + state.get("chargingProfile", {}).get("reductionOfChargeCurrent"), + ), + ) if drivetrain in set(COMBUSTION_ENGINE_DRIVE_TRAINS).intersection(HV_BATTERY_DRIVE_TRAINS): # for hybrid vehicles the remaining_range_fuel returned by the API seems to be the total remaining range diff --git a/bimmer_connected/vehicle/remote_services.py b/bimmer_connected/vehicle/remote_services.py index 426c3f89..604691a2 100644 --- a/bimmer_connected/vehicle/remote_services.py +++ b/bimmer_connected/vehicle/remote_services.py @@ -274,7 +274,7 @@ async def trigger_charging_profile_update( target_charging_profile = self._vehicle.charging_profile.format_for_remote_service() - if charging_mode and not charging_mode == ChargingMode.UNKNOWN: + if charging_mode and charging_mode != ChargingMode.UNKNOWN: target_charging_profile["chargingMode"]["type"] = MAP_CHARGING_MODE_TO_REMOTE_SERVICE[charging_mode] target_charging_profile["chargingMode"]["chargingPreference"] = CHARGING_MODE_TO_CHARGING_PREFERENCE[ charging_mode diff --git a/pyproject.toml b/pyproject.toml index e3f411eb..e0703138 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -22,14 +22,19 @@ exclude = [ [tool.ruff.lint] select = [ + "ASYNC", # flake8-async + "B", # flake8-bugbear "C", # complexity "D", # docstrings "E", # pycodestyle "F", # pyflakes/autoflake + "FLY", # flynt + "FURB", # refurb "I", # isort - "W", # pycodestyle - "UP", # pyupgrade "PGH004", # Use specific rule codes when using noqa + "SIM", # flake8-simplicity + "UP", # pyupgrade + "W", # pycodestyle ] ignore = [