chore: automatic commit 2025-04-30 12:48
This commit is contained in:
@@ -0,0 +1,57 @@
|
||||
from wtforms.widgets.core import CheckboxInput
|
||||
from wtforms.widgets.core import ColorInput
|
||||
from wtforms.widgets.core import DateInput
|
||||
from wtforms.widgets.core import DateTimeInput
|
||||
from wtforms.widgets.core import DateTimeLocalInput
|
||||
from wtforms.widgets.core import EmailInput
|
||||
from wtforms.widgets.core import FileInput
|
||||
from wtforms.widgets.core import HiddenInput
|
||||
from wtforms.widgets.core import html_params
|
||||
from wtforms.widgets.core import Input
|
||||
from wtforms.widgets.core import ListWidget
|
||||
from wtforms.widgets.core import MonthInput
|
||||
from wtforms.widgets.core import NumberInput
|
||||
from wtforms.widgets.core import Option
|
||||
from wtforms.widgets.core import PasswordInput
|
||||
from wtforms.widgets.core import RadioInput
|
||||
from wtforms.widgets.core import RangeInput
|
||||
from wtforms.widgets.core import SearchInput
|
||||
from wtforms.widgets.core import Select
|
||||
from wtforms.widgets.core import SubmitInput
|
||||
from wtforms.widgets.core import TableWidget
|
||||
from wtforms.widgets.core import TelInput
|
||||
from wtforms.widgets.core import TextArea
|
||||
from wtforms.widgets.core import TextInput
|
||||
from wtforms.widgets.core import TimeInput
|
||||
from wtforms.widgets.core import URLInput
|
||||
from wtforms.widgets.core import WeekInput
|
||||
|
||||
__all__ = [
|
||||
"CheckboxInput",
|
||||
"ColorInput",
|
||||
"DateInput",
|
||||
"DateTimeInput",
|
||||
"DateTimeLocalInput",
|
||||
"EmailInput",
|
||||
"FileInput",
|
||||
"HiddenInput",
|
||||
"ListWidget",
|
||||
"MonthInput",
|
||||
"NumberInput",
|
||||
"Option",
|
||||
"PasswordInput",
|
||||
"RadioInput",
|
||||
"RangeInput",
|
||||
"SearchInput",
|
||||
"Select",
|
||||
"SubmitInput",
|
||||
"TableWidget",
|
||||
"TextArea",
|
||||
"TextInput",
|
||||
"TelInput",
|
||||
"TimeInput",
|
||||
"URLInput",
|
||||
"WeekInput",
|
||||
"html_params",
|
||||
"Input",
|
||||
]
|
||||
Binary file not shown.
Binary file not shown.
569
venv/lib/python3.11/site-packages/wtforms/widgets/core.py
Normal file
569
venv/lib/python3.11/site-packages/wtforms/widgets/core.py
Normal file
@@ -0,0 +1,569 @@
|
||||
from markupsafe import escape
|
||||
from markupsafe import Markup
|
||||
|
||||
__all__ = (
|
||||
"CheckboxInput",
|
||||
"ColorInput",
|
||||
"DateInput",
|
||||
"DateTimeInput",
|
||||
"DateTimeLocalInput",
|
||||
"EmailInput",
|
||||
"FileInput",
|
||||
"HiddenInput",
|
||||
"ListWidget",
|
||||
"MonthInput",
|
||||
"NumberInput",
|
||||
"Option",
|
||||
"PasswordInput",
|
||||
"RadioInput",
|
||||
"RangeInput",
|
||||
"SearchInput",
|
||||
"Select",
|
||||
"SubmitInput",
|
||||
"TableWidget",
|
||||
"TextArea",
|
||||
"TextInput",
|
||||
"TelInput",
|
||||
"TimeInput",
|
||||
"URLInput",
|
||||
"WeekInput",
|
||||
)
|
||||
|
||||
|
||||
def clean_key(key):
|
||||
key = key.rstrip("_")
|
||||
if key.startswith("data_") or key.startswith("aria_"):
|
||||
key = key.replace("_", "-")
|
||||
return key
|
||||
|
||||
|
||||
def html_params(**kwargs):
|
||||
"""
|
||||
Generate HTML attribute syntax from inputted keyword arguments.
|
||||
|
||||
The output value is sorted by the passed keys, to provide consistent output
|
||||
each time this function is called with the same parameters. Because of the
|
||||
frequent use of the normally reserved keywords `class` and `for`, suffixing
|
||||
these with an underscore will allow them to be used.
|
||||
|
||||
In order to facilitate the use of ``data-`` and ``aria-`` attributes, if the
|
||||
name of the attribute begins with ``data_`` or ``aria_``, then every
|
||||
underscore will be replaced with a hyphen in the generated attribute.
|
||||
|
||||
>>> html_params(data_attr='user.name', aria_labeledby='name')
|
||||
'data-attr="user.name" aria-labeledby="name"'
|
||||
|
||||
In addition, the values ``True`` and ``False`` are special:
|
||||
* ``attr=True`` generates the HTML compact output of a boolean attribute,
|
||||
e.g. ``checked=True`` will generate simply ``checked``
|
||||
* ``attr=False`` will be ignored and generate no output.
|
||||
|
||||
>>> html_params(name='text1', id='f', class_='text')
|
||||
'class="text" id="f" name="text1"'
|
||||
>>> html_params(checked=True, readonly=False, name="text1", abc="hello")
|
||||
'abc="hello" checked name="text1"'
|
||||
|
||||
.. versionchanged:: 3.0
|
||||
``aria_`` args convert underscores to hyphens like ``data_``
|
||||
args.
|
||||
|
||||
.. versionchanged:: 2.2
|
||||
``data_`` args convert all underscores to hyphens, instead of
|
||||
only the first one.
|
||||
"""
|
||||
params = []
|
||||
for k, v in sorted(kwargs.items()):
|
||||
k = clean_key(k)
|
||||
if v is True:
|
||||
params.append(k)
|
||||
elif v is False:
|
||||
pass
|
||||
else:
|
||||
params.append(f'{str(k)}="{escape(v)}"') # noqa: B907
|
||||
return " ".join(params)
|
||||
|
||||
|
||||
class ListWidget:
|
||||
"""
|
||||
Renders a list of fields as a `ul` or `ol` list.
|
||||
|
||||
This is used for fields which encapsulate many inner fields as subfields.
|
||||
The widget will try to iterate the field to get access to the subfields and
|
||||
call them to render them.
|
||||
|
||||
If `prefix_label` is set, the subfield's label is printed before the field,
|
||||
otherwise afterwards. The latter is useful for iterating radios or
|
||||
checkboxes.
|
||||
"""
|
||||
|
||||
def __init__(self, html_tag="ul", prefix_label=True):
|
||||
assert html_tag in ("ol", "ul")
|
||||
self.html_tag = html_tag
|
||||
self.prefix_label = prefix_label
|
||||
|
||||
def __call__(self, field, **kwargs):
|
||||
kwargs.setdefault("id", field.id)
|
||||
html = [f"<{self.html_tag} {html_params(**kwargs)}>"]
|
||||
for subfield in field:
|
||||
if self.prefix_label:
|
||||
html.append(f"<li>{subfield.label} {subfield()}</li>")
|
||||
else:
|
||||
html.append(f"<li>{subfield()} {subfield.label}</li>")
|
||||
html.append(f"</{self.html_tag}>")
|
||||
return Markup("".join(html))
|
||||
|
||||
|
||||
class TableWidget:
|
||||
"""
|
||||
Renders a list of fields as a set of table rows with th/td pairs.
|
||||
|
||||
If `with_table_tag` is True, then an enclosing <table> is placed around the
|
||||
rows.
|
||||
|
||||
Hidden fields will not be displayed with a row, instead the field will be
|
||||
pushed into a subsequent table row to ensure XHTML validity. Hidden fields
|
||||
at the end of the field list will appear outside the table.
|
||||
"""
|
||||
|
||||
def __init__(self, with_table_tag=True):
|
||||
self.with_table_tag = with_table_tag
|
||||
|
||||
def __call__(self, field, **kwargs):
|
||||
html = []
|
||||
if self.with_table_tag:
|
||||
kwargs.setdefault("id", field.id)
|
||||
table_params = html_params(**kwargs)
|
||||
html.append(f"<table {table_params}>")
|
||||
hidden = ""
|
||||
for subfield in field:
|
||||
if subfield.type in ("HiddenField", "CSRFTokenField"):
|
||||
hidden += str(subfield)
|
||||
else:
|
||||
html.append(
|
||||
f"<tr><th>{subfield.label}</th><td>{hidden}{subfield}</td></tr>"
|
||||
)
|
||||
hidden = ""
|
||||
if self.with_table_tag:
|
||||
html.append("</table>")
|
||||
if hidden:
|
||||
html.append(hidden)
|
||||
return Markup("".join(html))
|
||||
|
||||
|
||||
class Input:
|
||||
"""
|
||||
Render a basic ``<input>`` field.
|
||||
|
||||
This is used as the basis for most of the other input fields.
|
||||
|
||||
By default, the `_value()` method will be called upon the associated field
|
||||
to provide the ``value=`` HTML attribute.
|
||||
"""
|
||||
|
||||
html_params = staticmethod(html_params)
|
||||
|
||||
def __init__(self, input_type=None):
|
||||
if input_type is not None:
|
||||
self.input_type = input_type
|
||||
|
||||
def __call__(self, field, **kwargs):
|
||||
kwargs.setdefault("id", field.id)
|
||||
kwargs.setdefault("type", self.input_type)
|
||||
if "value" not in kwargs:
|
||||
kwargs["value"] = field._value()
|
||||
flags = getattr(field, "flags", {})
|
||||
for k in dir(flags):
|
||||
if k in self.validation_attrs and k not in kwargs:
|
||||
kwargs[k] = getattr(flags, k)
|
||||
input_params = self.html_params(name=field.name, **kwargs)
|
||||
return Markup(f"<input {input_params}>")
|
||||
|
||||
|
||||
class TextInput(Input):
|
||||
"""
|
||||
Render a single-line text input.
|
||||
"""
|
||||
|
||||
input_type = "text"
|
||||
validation_attrs = [
|
||||
"required",
|
||||
"disabled",
|
||||
"readonly",
|
||||
"maxlength",
|
||||
"minlength",
|
||||
"pattern",
|
||||
]
|
||||
|
||||
|
||||
class PasswordInput(Input):
|
||||
"""
|
||||
Render a password input.
|
||||
|
||||
For security purposes, this field will not reproduce the value on a form
|
||||
submit by default. To have the value filled in, set `hide_value` to
|
||||
`False`.
|
||||
"""
|
||||
|
||||
input_type = "password"
|
||||
validation_attrs = [
|
||||
"required",
|
||||
"disabled",
|
||||
"readonly",
|
||||
"maxlength",
|
||||
"minlength",
|
||||
"pattern",
|
||||
]
|
||||
|
||||
def __init__(self, hide_value=True):
|
||||
self.hide_value = hide_value
|
||||
|
||||
def __call__(self, field, **kwargs):
|
||||
if self.hide_value:
|
||||
kwargs["value"] = ""
|
||||
return super().__call__(field, **kwargs)
|
||||
|
||||
|
||||
class HiddenInput(Input):
|
||||
"""
|
||||
Render a hidden input.
|
||||
"""
|
||||
|
||||
input_type = "hidden"
|
||||
validation_attrs = ["disabled"]
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
self.field_flags = {"hidden": True}
|
||||
|
||||
|
||||
class CheckboxInput(Input):
|
||||
"""
|
||||
Render a checkbox.
|
||||
|
||||
The ``checked`` HTML attribute is set if the field's data is a non-false value.
|
||||
"""
|
||||
|
||||
input_type = "checkbox"
|
||||
validation_attrs = ["required", "disabled"]
|
||||
|
||||
def __call__(self, field, **kwargs):
|
||||
if getattr(field, "checked", field.data):
|
||||
kwargs["checked"] = True
|
||||
return super().__call__(field, **kwargs)
|
||||
|
||||
|
||||
class RadioInput(Input):
|
||||
"""
|
||||
Render a single radio button.
|
||||
|
||||
This widget is most commonly used in conjunction with ListWidget or some
|
||||
other listing, as singular radio buttons are not very useful.
|
||||
"""
|
||||
|
||||
input_type = "radio"
|
||||
validation_attrs = ["required", "disabled"]
|
||||
|
||||
def __call__(self, field, **kwargs):
|
||||
if field.checked:
|
||||
kwargs["checked"] = True
|
||||
return super().__call__(field, **kwargs)
|
||||
|
||||
|
||||
class FileInput(Input):
|
||||
"""Render a file chooser input.
|
||||
|
||||
:param multiple: allow choosing multiple files
|
||||
"""
|
||||
|
||||
input_type = "file"
|
||||
validation_attrs = ["required", "disabled", "accept"]
|
||||
|
||||
def __init__(self, multiple=False):
|
||||
super().__init__()
|
||||
self.multiple = multiple
|
||||
|
||||
def __call__(self, field, **kwargs):
|
||||
# browser ignores value of file input for security
|
||||
kwargs["value"] = False
|
||||
|
||||
if self.multiple:
|
||||
kwargs["multiple"] = True
|
||||
|
||||
return super().__call__(field, **kwargs)
|
||||
|
||||
|
||||
class SubmitInput(Input):
|
||||
"""
|
||||
Renders a submit button.
|
||||
|
||||
The field's label is used as the text of the submit button instead of the
|
||||
data on the field.
|
||||
"""
|
||||
|
||||
input_type = "submit"
|
||||
validation_attrs = ["required", "disabled"]
|
||||
|
||||
def __call__(self, field, **kwargs):
|
||||
kwargs.setdefault("value", field.label.text)
|
||||
return super().__call__(field, **kwargs)
|
||||
|
||||
|
||||
class TextArea:
|
||||
"""
|
||||
Renders a multi-line text area.
|
||||
|
||||
`rows` and `cols` ought to be passed as keyword args when rendering.
|
||||
"""
|
||||
|
||||
validation_attrs = ["required", "disabled", "readonly", "maxlength", "minlength"]
|
||||
|
||||
def __call__(self, field, **kwargs):
|
||||
kwargs.setdefault("id", field.id)
|
||||
flags = getattr(field, "flags", {})
|
||||
for k in dir(flags):
|
||||
if k in self.validation_attrs and k not in kwargs:
|
||||
kwargs[k] = getattr(flags, k)
|
||||
textarea_params = html_params(name=field.name, **kwargs)
|
||||
textarea_innerhtml = escape(field._value())
|
||||
return Markup(
|
||||
f"<textarea {textarea_params}>\r\n{textarea_innerhtml}</textarea>"
|
||||
)
|
||||
|
||||
|
||||
class Select:
|
||||
"""
|
||||
Renders a select field.
|
||||
|
||||
If `multiple` is True, then the `size` property should be specified on
|
||||
rendering to make the field useful.
|
||||
|
||||
The field must provide an `iter_choices()` method which the widget will
|
||||
call on rendering; this method must yield tuples of
|
||||
`(value, label, selected)` or `(value, label, selected, render_kw)`.
|
||||
It also must provide a `has_groups()` method which tells whether choices
|
||||
are divided into groups, and if they do, the field must have an
|
||||
`iter_groups()` method that yields tuples of `(label, choices)`, where
|
||||
`choices` is a iterable of `(value, label, selected)` tuples.
|
||||
"""
|
||||
|
||||
validation_attrs = ["required", "disabled"]
|
||||
|
||||
def __init__(self, multiple=False):
|
||||
self.multiple = multiple
|
||||
|
||||
def __call__(self, field, **kwargs):
|
||||
kwargs.setdefault("id", field.id)
|
||||
if self.multiple:
|
||||
kwargs["multiple"] = True
|
||||
flags = getattr(field, "flags", {})
|
||||
for k in dir(flags):
|
||||
if k in self.validation_attrs and k not in kwargs:
|
||||
kwargs[k] = getattr(flags, k)
|
||||
select_params = html_params(name=field.name, **kwargs)
|
||||
html = [f"<select {select_params}>"]
|
||||
if field.has_groups():
|
||||
for group, choices in field.iter_groups():
|
||||
optgroup_params = html_params(label=group)
|
||||
html.append(f"<optgroup {optgroup_params}>")
|
||||
for choice in choices:
|
||||
val, label, selected, render_kw = choice
|
||||
html.append(self.render_option(val, label, selected, **render_kw))
|
||||
html.append("</optgroup>")
|
||||
else:
|
||||
for choice in field.iter_choices():
|
||||
val, label, selected, render_kw = choice
|
||||
html.append(self.render_option(val, label, selected, **render_kw))
|
||||
html.append("</select>")
|
||||
return Markup("".join(html))
|
||||
|
||||
@classmethod
|
||||
def render_option(cls, value, label, selected, **kwargs):
|
||||
if value is True:
|
||||
# Handle the special case of a 'True' value.
|
||||
value = str(value)
|
||||
|
||||
options = dict(kwargs, value=value)
|
||||
if selected:
|
||||
options["selected"] = True
|
||||
return Markup(f"<option {html_params(**options)}>{escape(label)}</option>")
|
||||
|
||||
|
||||
class Option:
|
||||
"""
|
||||
Renders the individual option from a select field.
|
||||
|
||||
This is just a convenience for various custom rendering situations, and an
|
||||
option by itself does not constitute an entire field.
|
||||
"""
|
||||
|
||||
def __call__(self, field, **kwargs):
|
||||
return Select.render_option(
|
||||
field._value(), field.label.text, field.checked, **kwargs
|
||||
)
|
||||
|
||||
|
||||
class SearchInput(Input):
|
||||
"""
|
||||
Renders an input with type "search".
|
||||
"""
|
||||
|
||||
input_type = "search"
|
||||
validation_attrs = [
|
||||
"required",
|
||||
"disabled",
|
||||
"readonly",
|
||||
"maxlength",
|
||||
"minlength",
|
||||
"pattern",
|
||||
]
|
||||
|
||||
|
||||
class TelInput(Input):
|
||||
"""
|
||||
Renders an input with type "tel".
|
||||
"""
|
||||
|
||||
input_type = "tel"
|
||||
validation_attrs = [
|
||||
"required",
|
||||
"disabled",
|
||||
"readonly",
|
||||
"maxlength",
|
||||
"minlength",
|
||||
"pattern",
|
||||
]
|
||||
|
||||
|
||||
class URLInput(Input):
|
||||
"""
|
||||
Renders an input with type "url".
|
||||
"""
|
||||
|
||||
input_type = "url"
|
||||
validation_attrs = [
|
||||
"required",
|
||||
"disabled",
|
||||
"readonly",
|
||||
"maxlength",
|
||||
"minlength",
|
||||
"pattern",
|
||||
]
|
||||
|
||||
|
||||
class EmailInput(Input):
|
||||
"""
|
||||
Renders an input with type "email".
|
||||
"""
|
||||
|
||||
input_type = "email"
|
||||
validation_attrs = [
|
||||
"required",
|
||||
"disabled",
|
||||
"readonly",
|
||||
"maxlength",
|
||||
"minlength",
|
||||
"pattern",
|
||||
]
|
||||
|
||||
|
||||
class DateTimeInput(Input):
|
||||
"""
|
||||
Renders an input with type "datetime".
|
||||
"""
|
||||
|
||||
input_type = "datetime"
|
||||
validation_attrs = ["required", "disabled", "readonly", "max", "min", "step"]
|
||||
|
||||
|
||||
class DateInput(Input):
|
||||
"""
|
||||
Renders an input with type "date".
|
||||
"""
|
||||
|
||||
input_type = "date"
|
||||
validation_attrs = ["required", "disabled", "readonly", "max", "min", "step"]
|
||||
|
||||
|
||||
class MonthInput(Input):
|
||||
"""
|
||||
Renders an input with type "month".
|
||||
"""
|
||||
|
||||
input_type = "month"
|
||||
validation_attrs = ["required", "disabled", "readonly", "max", "min", "step"]
|
||||
|
||||
|
||||
class WeekInput(Input):
|
||||
"""
|
||||
Renders an input with type "week".
|
||||
"""
|
||||
|
||||
input_type = "week"
|
||||
validation_attrs = ["required", "disabled", "readonly", "max", "min", "step"]
|
||||
|
||||
|
||||
class TimeInput(Input):
|
||||
"""
|
||||
Renders an input with type "time".
|
||||
"""
|
||||
|
||||
input_type = "time"
|
||||
validation_attrs = ["required", "disabled", "readonly", "max", "min", "step"]
|
||||
|
||||
|
||||
class DateTimeLocalInput(Input):
|
||||
"""
|
||||
Renders an input with type "datetime-local".
|
||||
"""
|
||||
|
||||
input_type = "datetime-local"
|
||||
validation_attrs = ["required", "disabled", "readonly", "max", "min", "step"]
|
||||
|
||||
|
||||
class NumberInput(Input):
|
||||
"""
|
||||
Renders an input with type "number".
|
||||
"""
|
||||
|
||||
input_type = "number"
|
||||
validation_attrs = ["required", "disabled", "readonly", "max", "min", "step"]
|
||||
|
||||
def __init__(self, step=None, min=None, max=None):
|
||||
self.step = step
|
||||
self.min = min
|
||||
self.max = max
|
||||
|
||||
def __call__(self, field, **kwargs):
|
||||
if self.step is not None:
|
||||
kwargs.setdefault("step", self.step)
|
||||
if self.min is not None:
|
||||
kwargs.setdefault("min", self.min)
|
||||
if self.max is not None:
|
||||
kwargs.setdefault("max", self.max)
|
||||
return super().__call__(field, **kwargs)
|
||||
|
||||
|
||||
class RangeInput(Input):
|
||||
"""
|
||||
Renders an input with type "range".
|
||||
"""
|
||||
|
||||
input_type = "range"
|
||||
validation_attrs = ["disabled", "max", "min", "step"]
|
||||
|
||||
def __init__(self, step=None):
|
||||
self.step = step
|
||||
|
||||
def __call__(self, field, **kwargs):
|
||||
if self.step is not None:
|
||||
kwargs.setdefault("step", self.step)
|
||||
return super().__call__(field, **kwargs)
|
||||
|
||||
|
||||
class ColorInput(Input):
|
||||
"""
|
||||
Renders an input with type "color".
|
||||
"""
|
||||
|
||||
input_type = "color"
|
||||
validation_attrs = ["disabled"]
|
||||
Reference in New Issue
Block a user