Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.11/site-packages/wtforms/datalist.py: 37%
Shortcuts on this page
r m x toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
Shortcuts on this page
r m x toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
1import warnings
2from dataclasses import dataclass
3from dataclasses import field
5from wtforms import widgets
6from wtforms._compat import get_signature
7from wtforms.fields.choices import Choice
9__all__ = ("DataList", "DataListChoice")
12@dataclass
13class DataListChoice:
14 """
15 An option declared via :class:`~wtforms.DataList`'s ``choices=``
16 parameter.
18 :param value:
19 The value rendered as the ``<option>``'s ``value`` attribute.
20 :param label:
21 The label of the option. Defaults to ``value`` when omitted.
22 :param render_kw:
23 A dict containing HTML attributes that will be rendered
24 with the option. Defaults to an empty dict when omitted.
25 """
27 value: str
28 label: str | None = None
29 render_kw: dict = field(default_factory=dict)
31 def __post_init__(self):
32 if self.label is None:
33 self.label = self.value
35 def __iter__(self):
36 return iter((self.value, self.label, self.render_kw))
38 @classmethod
39 def from_enum(cls, enum_cls, *, label=None):
40 """Build a list of choices from an :class:`enum.Enum` class.
42 See :meth:`SelectChoice.from_enum` for details.
43 """
44 if label is None:
45 label = str if "__str__" in enum_cls.__dict__ else lambda m: m.name
46 return [cls(value=m.name, label=label(m)) for m in enum_cls]
48 @classmethod
49 def from_input(cls, input):
50 """Coerce a value passed by the user into a :class:`DataListChoice`."""
51 if isinstance(input, DataListChoice):
52 return input
54 if isinstance(input, Choice):
55 warnings.warn(
56 "Passing Choice to a DataList is deprecated; Choice is the "
57 "output type returned by iter_choices(). Use DataListChoice "
58 "instead. Support for Choice as input will be removed in "
59 "WTForms 4.0.",
60 DeprecationWarning,
61 stacklevel=4,
62 )
63 return cls(
64 value=input.value,
65 label=input.label,
66 render_kw=input.render_kw,
67 )
69 if isinstance(input, str):
70 return cls(value=input)
72 if isinstance(input, tuple):
73 return cls(*input)
76class DataList:
77 """A ``<datalist>`` of suggestions attached to a single field.
79 Passed to a :class:`~wtforms.Field` via its ``datalist=`` parameter
80 to add an autocomplete-style list of choices. See the WTForms
81 fields documentation for usage.
82 """
84 widget = widgets.DataListWidget()
86 def __init__(self, choices=None, *, render_kw=None, widget=None):
87 self._raw_choices = choices
88 self._choices = None if callable(choices) else choices
89 self.render_kw = render_kw or {}
90 if widget is not None:
91 self.widget = widget
92 self.id = None
94 def _clone(self, id):
95 clone = DataList.__new__(DataList)
96 clone._raw_choices = self._raw_choices
97 clone._choices = None if callable(self._raw_choices) else self._raw_choices
98 clone.render_kw = self.render_kw
99 clone.widget = self.widget
100 clone.id = id
101 return clone
103 def _resolve(self, field):
104 raw = self._raw_choices
105 if not callable(raw):
106 return
107 try:
108 sig = get_signature(raw)
109 sig.bind(field._form, field)
110 except TypeError:
111 self._choices = raw()
112 return
113 self._choices = raw(field._form, field)
115 def iter_choices(self, field=None):
116 raw = self._choices
117 if raw is None:
118 return []
119 return [DataListChoice.from_input(item) for item in raw]
121 def __call__(self, field=None, **kwargs):
122 return self.widget(self, field=field, **kwargs)