初始化奇妙小屏幕控制器项目
This commit is contained in:
@@ -0,0 +1,43 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import re
|
||||
from typing import Any
|
||||
|
||||
RGB = tuple[int, int, int]
|
||||
HEX_RE = re.compile(r"^#([0-9a-fA-F]{6})$")
|
||||
|
||||
|
||||
def parse_color(value: Any) -> RGB:
|
||||
if isinstance(value, str):
|
||||
match = HEX_RE.match(value.strip())
|
||||
if not match:
|
||||
raise ValueError("color must be #RRGGBB")
|
||||
raw = match.group(1)
|
||||
return int(raw[0:2], 16), int(raw[2:4], 16), int(raw[4:6], 16)
|
||||
|
||||
if isinstance(value, dict):
|
||||
try:
|
||||
return validate_rgb((value["r"], value["g"], value["b"]))
|
||||
except KeyError as exc:
|
||||
raise ValueError("color object must contain r, g, and b") from exc
|
||||
|
||||
if isinstance(value, (list, tuple)) and len(value) == 3:
|
||||
return validate_rgb(value)
|
||||
|
||||
raise ValueError("color must be #RRGGBB or {r,g,b}")
|
||||
|
||||
|
||||
def validate_rgb(value: Any) -> RGB:
|
||||
try:
|
||||
channels = tuple(int(channel) for channel in value)
|
||||
except Exception as exc:
|
||||
raise ValueError("RGB channels must be integers") from exc
|
||||
|
||||
if len(channels) != 3:
|
||||
raise ValueError("RGB color must have three channels")
|
||||
|
||||
if any(channel < 0 or channel > 255 for channel in channels):
|
||||
raise ValueError("RGB channels must be in 0..255")
|
||||
|
||||
return channels # type: ignore[return-value]
|
||||
|
||||
Reference in New Issue
Block a user