Skip to content

Commit 6019429

Browse files
authored
Merge pull request #40 from kratisinghh/main
Prefer RGB for 3-element tuples and make HSL parsing explicit
2 parents 4819081 + 9731fed commit 6019429

File tree

1 file changed

+26
-27
lines changed

1 file changed

+26
-27
lines changed

src/cm_colors/core/color_parser.py

Lines changed: 26 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -96,26 +96,10 @@ def parse_color_to_rgb(
9696
# 1. Normalise tuple/list inputs first
9797
if isinstance(color, (tuple, list)):
9898
ln = len(color)
99+
99100
if ln == 3:
100-
# 3-component tuple/list - DEFAULT TO RGB (most common case)
101-
# Only treat as HSL if explicitly float values in 0-1 range for s,l AND h <= 360
102-
r_raw, g_raw, b_raw = color
103-
104-
# Check if this looks like HSL: h <= 360, s and l are floats in [0,1]
105-
if (
106-
isinstance(r_raw, (int, float))
107-
and 1 < float(r_raw) <= 360
108-
and isinstance(g_raw, float)
109-
and 0.0 <= float(g_raw) <= 1.0
110-
and isinstance(b_raw, float)
111-
and 0.0 <= float(b_raw) <= 1.0
112-
and not isinstance(g_raw, int)
113-
and not isinstance(b_raw, int)
114-
):
115-
# This looks like HSL: (hue, saturation_float, lightness_float)
116-
return hsl_to_rgb(color)
117-
else:
118-
# Default to RGB processing
101+
# Always try RGB first
102+
try:
119103
comps = []
120104
for c in color:
121105
if isinstance(c, (int, float)):
@@ -126,24 +110,38 @@ def parse_color_to_rgb(
126110
elif isinstance(c, float) and 0.0 <= c <= 255.0:
127111
comps.append(int(round(c)))
128112
else:
129-
raise ValueError(
130-
f"RGB component out of range or invalid: {c}"
131-
)
113+
raise ValueError(f"RGB component out of range or invalid: {c}")
132114
elif isinstance(c, str):
133115
comps.append(int(round(_parse_number_token(c, component=True))))
134116
else:
135117
raise ValueError(
136118
f"Unsupported RGB component type: {type(c).__name__}"
137119
)
138120

139-
rgb = tuple(max(0, min(255, int(round(x)))) for x in comps)
121+
rgb = tuple(int(round(x)) for x in comps)
122+
140123
if not is_valid_rgb(rgb):
141-
raise ValueError(f"Invalid RGB tuple after parsing: {rgb}")
124+
raise ValueError(f"RGB component out of range or invalid: {rgb}")
125+
142126
return rgb
143127

128+
129+
except ValueError as e:
130+
# If this was clearly an RGB range error, do NOT fallback
131+
if "out of range" in str(e):
132+
raise
133+
134+
# Otherwise, try HSL fallback
135+
try:
136+
return hsl_to_rgb(color)
137+
except Exception:
138+
raise ValueError(
139+
"Invalid color tuple. If you intended HSL, use hsl(...) syntax."
140+
)
141+
142+
144143
elif ln == 4:
145144
# 4-component tuple: RGBA or HSLA
146-
# Heuristic: if any of first 3 values are > 1 or integers, treat as RGBA
147145
r_raw, g_raw, b_raw, a_raw = color
148146

149147
looks_like_rgb = (
@@ -156,18 +154,18 @@ def parse_color_to_rgb(
156154
)
157155

158156
if looks_like_rgb:
159-
# Treat as RGBA
160157
r = int(round(_parse_number_token(str(r_raw), component=True)))
161158
g = int(round(_parse_number_token(str(g_raw), component=True)))
162159
b = int(round(_parse_number_token(str(b_raw), component=True)))
163160
a = _parse_number_token(str(a_raw), component=False)
164161

165-
# resolve background
166162
if background is None:
167163
bg_rgb = (255, 255, 255)
168164
else:
169165
bg_rgb = parse_color_to_rgb(background)
166+
170167
return rgba_to_rgb((r, g, b, a), background=bg_rgb)
168+
171169
else:
172170
bg_rgb = None
173171
if background is not None:
@@ -176,6 +174,7 @@ def parse_color_to_rgb(
176174
else:
177175
bg_rgb = parse_color_to_rgb(background)
178176
return hsla_to_rgb(color, bg_rgb)
177+
179178
else:
180179
raise ValueError(
181180
f"Tuple/list color must have length 3 (RGB/HSL) or 4 (RGBA/HSLA). Got length {ln}"

0 commit comments

Comments
 (0)