Files
glitchtip-backend/bitfield/forms.py
T
2023-04-13 11:41:28 -04:00

65 lines
2.2 KiB
Python

from __future__ import absolute_import
from django.forms import CheckboxSelectMultiple, IntegerField, ValidationError
from django.utils.encoding import force_str
from bitfield.types import BitHandler
class BitFieldCheckboxSelectMultiple(CheckboxSelectMultiple):
def render(self, name, value, attrs=None, choices=(), renderer=None):
if isinstance(value, BitHandler):
value = [k for k, v in value if v]
elif isinstance(value, int):
real_value = []
div = 2
for k, v in self.choices:
if value % div != 0:
real_value.append(k)
value -= value % div
div *= 2
value = real_value
return super(BitFieldCheckboxSelectMultiple, self).render(
name, value, attrs=attrs
)
def has_changed(self, initial, data):
if initial is None:
initial = []
if data is None:
data = []
if initial != data:
return True
initial_set = set([force_str(value) for value in initial])
data_set = set([force_str(value) for value in data])
return data_set != initial_set
class BitFormField(IntegerField):
def __init__(
self, choices=(), widget=BitFieldCheckboxSelectMultiple, *args, **kwargs
):
if isinstance(kwargs["initial"], int):
iv = kwargs["initial"]
iv_list = []
for i in range(0, min(len(choices), 63)):
if (1 << i) & iv > 0:
iv_list += [choices[i][0]]
kwargs["initial"] = iv_list
self.widget = widget
super(BitFormField, self).__init__(widget=widget, *args, **kwargs)
self.choices = self.widget.choices = choices
def clean(self, value):
if not value:
return 0
# Assume an iterable which contains an item per flag that's enabled
result = BitHandler(0, [k for k, v in self.choices])
for k in value:
try:
setattr(result, str(k), True)
except AttributeError:
raise ValidationError("Unknown choice: %r" % (k,))
return int(result)