class ChoiceField:
def __init__(self, value, label):
self.value = value
self.label = label
def __eq__(self, other):
if isinstance(other, Field):
return self.value == other.value
return self.value == other
def __str__(self):
return self.value
class ChoicesMeta(type):
def __new__(cls, name, bases, attrs):
new_cls = super().__new__(cls, name, bases, attrs)
fields = [(attr_name, attr_value) for attr_name, attr_value in attrs.items()
if not attr_name.startswith('_') and isinstance(attr_value, Field)]
setattr(new_cls, "_fields", fields)
return new_cls
def __call__(cls, value):
for _, field in cls._fields:
if field.value == value:
return field
raise ValueError(f"Invalid value: {value}")
def __iter__(cls):
return (field for _, field in cls._fields)
def __contains__(cls, value):
return value in [item.value for _, item in cls._fields]
class Choices(metaclass=ChoicesMeta):
@classmethod
def choices(cls):
return [(item.value, item.label) for _, item in cls._fields]
@classmethod
def help_text(cls):
return ", ".join([f"{item.value}: {item.label}" for _, item in cls._fields])
@classmethod
def values(cls):
return [item.value for _, item in cls._fields]
@classmethod
def validator(cls, value):
values = cls.values()
if value not in values:
raise ValueError(f"Invalid value: {value}, valid values: {values}")
return value