"""Enumeration classes for configuration options.
This module contains all enumeration classes used throughout the configuration
system to ensure type safety and provide clear, validated options.
"""
from enum import Enum
from typing import Any
class ConnectivityMode(str, Enum):
"""Module connectivity detection modes.
Attributes:
FOUR_WAY: Connect only to orthogonal neighbors (up, down, left, right)
EIGHT_WAY: Connect to all 8 neighbors including diagonals
"""
FOUR_WAY = "4-way"
EIGHT_WAY = "8-way"
def __str__(self) -> str:
"""Return the enum value for string representation."""
return self.value
@classmethod
def _missing_(cls, value: Any) -> "ConnectivityMode":
"""Handle case-insensitive lookup and common aliases."""
if isinstance(value, str):
value_lower = value.lower().strip()
for member in cls:
if member.value.lower() == value_lower:
return member
# Handle aliases
aliases = {
"4way": cls.FOUR_WAY,
"4-way": cls.FOUR_WAY,
"four": cls.FOUR_WAY,
"orthogonal": cls.FOUR_WAY,
"8way": cls.EIGHT_WAY,
"8-way": cls.EIGHT_WAY,
"eight": cls.EIGHT_WAY,
"diagonal": cls.EIGHT_WAY,
"all": cls.EIGHT_WAY,
}
if value_lower in aliases:
return aliases[value_lower]
raise ValueError(f"'{value}' is not a valid {cls.__name__}")
class MergeStrategy(str, Enum):
"""Module merging strategies.
Attributes:
NONE: No merging, each module rendered separately
SOFT: Merge adjacent connected modules with smooth transitions
AGGRESSIVE: Extensive merging creating flowing organic shapes
"""
NONE = "none"
SOFT = "soft"
AGGRESSIVE = "aggressive"
def __str__(self) -> str:
"""Return the enum value for string representation."""
return self.value
@classmethod
def _missing_(cls, value: Any) -> "MergeStrategy":
"""Handle case-insensitive lookup and common aliases."""
if isinstance(value, str):
value_lower = value.lower().strip()
for member in cls:
if member.value.lower() == value_lower:
return member
# Handle aliases
aliases = {
"no": cls.NONE,
"off": cls.NONE,
"false": cls.NONE,
"disabled": cls.NONE,
"smooth": cls.SOFT,
"medium": cls.SOFT,
"moderate": cls.SOFT,
"hard": cls.AGGRESSIVE,
"strong": cls.AGGRESSIVE,
"max": cls.AGGRESSIVE,
"maximum": cls.AGGRESSIVE,
"full": cls.AGGRESSIVE,
}
if value_lower in aliases:
return aliases[value_lower]
raise ValueError(f"'{value}' is not a valid {cls.__name__}")
class ReserveMode(str, Enum):
"""Reserve area interaction mode enumeration.
Attributes:
KNOCKOUT: Clear modules completely from reserve area (default)
IMPRINT: Overlay centerpiece while preserving modules underneath for scanability
"""
KNOCKOUT = "knockout"
IMPRINT = "imprint"
def __str__(self) -> str:
"""Return the enum value for string representation."""
return self.value
@classmethod
def _missing_(cls, value: Any) -> "ReserveMode":
"""Handle case-insensitive lookup and common aliases."""
if isinstance(value, str):
value_lower = value.lower().strip()
for member in cls:
if member.value.lower() == value_lower:
return member
# Handle aliases
aliases = {
"clear": cls.KNOCKOUT,
"remove": cls.KNOCKOUT,
"cut": cls.KNOCKOUT,
"overlay": cls.IMPRINT,
"preserve": cls.IMPRINT,
"keep": cls.IMPRINT,
}
if value_lower in aliases:
return aliases[value_lower]
raise ValueError(f"'{value}' is not a valid {cls.__name__}")
class PlacementMode(str, Enum):
"""Reserve area placement mode enumeration.
Attributes:
CUSTOM: Use custom offset_x and offset_y values (default)
CENTER: Center of QR code
TOP_LEFT: Top-left corner
TOP_RIGHT: Top-right corner
BOTTOM_LEFT: Bottom-left corner
BOTTOM_RIGHT: Bottom-right corner
TOP_CENTER: Top edge center
BOTTOM_CENTER: Bottom edge center
LEFT_CENTER: Left edge center
RIGHT_CENTER: Right edge center
"""
CUSTOM = "custom"
CENTER = "center"
TOP_LEFT = "top-left"
TOP_RIGHT = "top-right"
BOTTOM_LEFT = "bottom-left"
BOTTOM_RIGHT = "bottom-right"
TOP_CENTER = "top-center"
BOTTOM_CENTER = "bottom-center"
LEFT_CENTER = "left-center"
RIGHT_CENTER = "right-center"
def __str__(self) -> str:
"""Return the enum value for string representation."""
return self.value
@classmethod
def _missing_(cls, value: Any) -> "PlacementMode":
"""Handle case-insensitive lookup and common aliases."""
if isinstance(value, str):
value_lower = value.lower().strip().replace("_", "-")
for member in cls:
if member.value.lower() == value_lower:
return member
# Handle aliases with underscores/spaces
aliases = {
"topleft": cls.TOP_LEFT,
"top_left": cls.TOP_LEFT,
"topright": cls.TOP_RIGHT,
"top_right": cls.TOP_RIGHT,
"bottomleft": cls.BOTTOM_LEFT,
"bottom_left": cls.BOTTOM_LEFT,
"bottomright": cls.BOTTOM_RIGHT,
"bottom_right": cls.BOTTOM_RIGHT,
"topcenter": cls.TOP_CENTER,
"top_center": cls.TOP_CENTER,
"bottomcenter": cls.BOTTOM_CENTER,
"bottom_center": cls.BOTTOM_CENTER,
"leftcenter": cls.LEFT_CENTER,
"left_center": cls.LEFT_CENTER,
"rightcenter": cls.RIGHT_CENTER,
"right_center": cls.RIGHT_CENTER,
"middle": cls.CENTER,
}
if value_lower in aliases:
return aliases[value_lower]
raise ValueError(f"'{value}' is not a valid {cls.__name__}")
[docs]
class ModuleShape(str, Enum):
"""Base module shape types.
Attributes:
SQUARE: Traditional square modules
CIRCLE: Circular modules (may have gaps)
ROUNDED: Square with rounded corners
DOT: Small circular dots
DIAMOND: 45-degree rotated square
STAR: 5-pointed star modules
HEXAGON: Hexagonal modules
TRIANGLE: Triangular modules
SQUIRCLE: Superellipse shape (between square and circle)
CROSS: Cross/plus shaped modules
CONNECTED: Basic connected style with rounded corners
CONNECTED_EXTRA_ROUNDED: Extra smooth curves using quadratic beziers
CONNECTED_CLASSY: Boundary-focused styling with strategic rounding
CONNECTED_CLASSY_ROUNDED: Classy style with extra-rounded corners
"""
SQUARE = "square"
CIRCLE = "circle"
ROUNDED = "rounded"
DOT = "dot"
DIAMOND = "diamond"
STAR = "star"
HEXAGON = "hexagon"
TRIANGLE = "triangle"
SQUIRCLE = "squircle"
CROSS = "cross"
CONNECTED = "connected"
CONNECTED_EXTRA_ROUNDED = "connected-extra-rounded"
CONNECTED_CLASSY = "connected-classy"
CONNECTED_CLASSY_ROUNDED = "connected-classy-rounded"
[docs]
def __str__(self) -> str:
"""Return the enum value for string representation."""
return self.value
@classmethod
def _missing_(cls, value: Any) -> "ModuleShape":
"""Handle case-insensitive lookup and common aliases."""
if isinstance(value, str):
value_lower = value.lower().strip().replace("_", "-")
for member in cls:
if member.value.lower() == value_lower:
return member
# Handle aliases
aliases = {
"rect": cls.SQUARE,
"rectangle": cls.SQUARE,
"round": cls.CIRCLE,
"circular": cls.CIRCLE,
"smooth": cls.ROUNDED,
"round-corner": cls.ROUNDED,
"round_corner": cls.ROUNDED,
"point": cls.DOT,
"pixel": cls.DOT,
"rhombus": cls.DIAMOND,
"hex": cls.HEXAGON,
"tri": cls.TRIANGLE,
"plus": cls.CROSS,
"flow": cls.CONNECTED,
"smooth-connected": cls.CONNECTED_EXTRA_ROUNDED,
"smooth_connected": cls.CONNECTED_EXTRA_ROUNDED,
"extra-rounded": cls.CONNECTED_EXTRA_ROUNDED,
"extra_rounded": cls.CONNECTED_EXTRA_ROUNDED,
"classy": cls.CONNECTED_CLASSY,
"elegant": cls.CONNECTED_CLASSY,
"classy-rounded": cls.CONNECTED_CLASSY_ROUNDED,
"classy_rounded": cls.CONNECTED_CLASSY_ROUNDED,
}
if value_lower in aliases:
return aliases[value_lower]
raise ValueError(f"'{value}' is not a valid {cls.__name__}")
[docs]
class FinderShape(str, Enum):
"""Finder pattern shape types.
Attributes:
SQUARE: Traditional square finder patterns
ROUNDED: Rounded square finder patterns
CIRCLE: Circular finder patterns
"""
SQUARE = "square"
ROUNDED = "rounded"
CIRCLE = "circle"
[docs]
def __str__(self) -> str:
"""Return the enum value for string representation."""
return self.value
@classmethod
def _missing_(cls, value: Any) -> "FinderShape":
"""Handle case-insensitive lookup and common aliases."""
if isinstance(value, str):
value_lower = value.lower().strip()
for member in cls:
if member.value.lower() == value_lower:
return member
# Handle aliases
aliases = {
"rect": cls.SQUARE,
"rectangle": cls.SQUARE,
"smooth": cls.ROUNDED,
"round-corner": cls.ROUNDED,
"round_corner": cls.ROUNDED,
"round": cls.CIRCLE,
"circular": cls.CIRCLE,
}
if value_lower in aliases:
return aliases[value_lower]
raise ValueError(f"'{value}' is not a valid {cls.__name__}")
class ContourMode(str, Enum):
"""Contour rendering modes for Phase 3.
Attributes:
BEZIER: Use Bezier curves for smooth contours
COMBINED: Combine multiple contour strategies
OVERLAY: Overlay contours on existing shapes
"""
BEZIER = "bezier"
COMBINED = "combined"
OVERLAY = "overlay"
def __str__(self) -> str:
"""Return the enum value for string representation."""
return self.value
@classmethod
def _missing_(cls, value: Any) -> "ContourMode":
"""Handle case-insensitive lookup and common aliases."""
if isinstance(value, str):
value_lower = value.lower().strip()
for member in cls:
if member.value.lower() == value_lower:
return member
# Handle aliases
aliases = {
"curve": cls.BEZIER,
"curves": cls.BEZIER,
"smooth": cls.BEZIER,
"multi": cls.COMBINED,
"multiple": cls.COMBINED,
"mixed": cls.COMBINED,
"hybrid": cls.COMBINED,
"layer": cls.OVERLAY,
"layered": cls.OVERLAY,
"over": cls.OVERLAY,
}
if value_lower in aliases:
return aliases[value_lower]
raise ValueError(f"'{value}' is not a valid {cls.__name__}")
class OptimizationLevel(str, Enum):
"""Optimization levels for Bezier curve generation.
Attributes:
LOW: Minimal optimization, fastest rendering
MEDIUM: Balanced optimization (default)
HIGH: Maximum optimization, smallest file size
"""
LOW = "low"
MEDIUM = "medium"
HIGH = "high"
def __str__(self) -> str:
"""Return the enum value for string representation."""
return self.value
@classmethod
def _missing_(cls, value: Any) -> "OptimizationLevel":
"""Handle case-insensitive lookup and common aliases."""
if isinstance(value, str):
value_lower = value.lower().strip()
for member in cls:
if member.value.lower() == value_lower:
return member
# Handle aliases
aliases = {
"min": cls.LOW,
"minimal": cls.LOW,
"fast": cls.LOW,
"fastest": cls.LOW,
"none": cls.LOW,
"med": cls.MEDIUM,
"balanced": cls.MEDIUM,
"normal": cls.MEDIUM,
"default": cls.MEDIUM,
"max": cls.HIGH,
"maximum": cls.HIGH,
"best": cls.HIGH,
"full": cls.HIGH,
}
if value_lower in aliases:
return aliases[value_lower]
raise ValueError(f"'{value}' is not a valid {cls.__name__}")