Skip to content

Commit a6a0625

Browse files
refactor: auto-generate enum lookups and use JSON parsing for B2C errors
Phase 2 of dynamic typing hardening: - Replace 5 hand-maintained string-to-enum lookup dicts in cli.py with kebab_name()-based auto-generation from enum definitions - HeatMode lookup uses explicit member subset (NORMAL, BOOST, ECO) - Replace fragile '"status":"400"' string matching in b2c_login.py with proper json.loads() parsing and try/except fallback Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 6a71b66 commit a6a0625

2 files changed

Lines changed: 14 additions & 32 deletions

File tree

src/flameconnect/b2c_login.py

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
from __future__ import annotations
88

9+
import json
910
import logging
1011
import re
1112
from typing import NamedTuple
@@ -246,9 +247,13 @@ async def b2c_login_with_credentials(auth_uri: str, email: str, password: str) -
246247
raise AuthenticationError(
247248
f"Credential submission returned HTTP {resp.status}"
248249
)
249-
# Check for error in the JSON-like response
250-
if '"status":"400"' in body or '"status": "400"' in body:
251-
raise AuthenticationError("Invalid email or password")
250+
# Check for error in the JSON response
251+
try:
252+
resp_data = json.loads(body)
253+
if str(resp_data.get("status")) == "400":
254+
raise AuthenticationError("Invalid email or password")
255+
except (json.JSONDecodeError, KeyError, TypeError):
256+
pass
252257
# Merge cookies set by the POST response (e.g.
253258
# updated x-ms-cpim-cache and x-ms-cpim-trans)
254259
# into the cookie header for the confirmed GET.

src/flameconnect/cli.py

Lines changed: 6 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@
5050
TimerStatus,
5151
convert_temp,
5252
display_name,
53+
kebab_name,
5354
temp_suffix,
5455
)
5556

@@ -67,42 +68,18 @@
6768

6869
# Mapping from CLI heat-mode string to HeatMode enum value
6970
_HEAT_MODE_LOOKUP: dict[str, HeatMode] = {
70-
"normal": HeatMode.NORMAL,
71-
"boost": HeatMode.BOOST,
72-
"eco": HeatMode.ECO,
71+
kebab_name(m): m for m in (HeatMode.NORMAL, HeatMode.BOOST, HeatMode.ECO)
7372
}
7473

7574
_PULSATING_LOOKUP: dict[str, PulsatingEffect] = {
76-
"on": PulsatingEffect.ON,
77-
"off": PulsatingEffect.OFF,
75+
kebab_name(m): m for m in PulsatingEffect
7876
}
7977

80-
_FLAME_COLOR_LOOKUP: dict[str, FlameColor] = {
81-
"all": FlameColor.ALL,
82-
"yellow-red": FlameColor.YELLOW_RED,
83-
"yellow-blue": FlameColor.YELLOW_BLUE,
84-
"blue": FlameColor.BLUE,
85-
"red": FlameColor.RED,
86-
"yellow": FlameColor.YELLOW,
87-
"blue-red": FlameColor.BLUE_RED,
88-
}
78+
_FLAME_COLOR_LOOKUP: dict[str, FlameColor] = {kebab_name(m): m for m in FlameColor}
8979

90-
_MEDIA_THEME_LOOKUP: dict[str, MediaTheme] = {
91-
"user-defined": MediaTheme.USER_DEFINED,
92-
"white": MediaTheme.WHITE,
93-
"blue": MediaTheme.BLUE,
94-
"purple": MediaTheme.PURPLE,
95-
"red": MediaTheme.RED,
96-
"green": MediaTheme.GREEN,
97-
"prism": MediaTheme.PRISM,
98-
"kaleidoscope": MediaTheme.KALEIDOSCOPE,
99-
"midnight": MediaTheme.MIDNIGHT,
100-
}
80+
_MEDIA_THEME_LOOKUP: dict[str, MediaTheme] = {kebab_name(m): m for m in MediaTheme}
10181

102-
_TEMP_UNIT_LOOKUP: dict[str, TempUnit] = {
103-
"fahrenheit": TempUnit.FAHRENHEIT,
104-
"celsius": TempUnit.CELSIUS,
105-
}
82+
_TEMP_UNIT_LOOKUP: dict[str, TempUnit] = {kebab_name(m): m for m in TempUnit}
10683

10784

10885
class _FlameEffectSetter(NamedTuple):

0 commit comments

Comments
 (0)