Team Ai
Datasetpublic

codekingpro/portable-devtools

sourceHugging Faceupdated 5mo agoView on Hugging Face
1likes14kdownloads
core.py584 linesDownload Raw Back to widgets
1import warnings2 3from markupsafe import escape4from markupsafe import Markup5 6__all__ = (7    "CheckboxInput",8    "ColorInput",9    "DateInput",10    "DateTimeInput",11    "DateTimeLocalInput",12    "EmailInput",13    "FileInput",14    "HiddenInput",15    "ListWidget",16    "MonthInput",17    "NumberInput",18    "Option",19    "PasswordInput",20    "RadioInput",21    "RangeInput",22    "SearchInput",23    "Select",24    "SubmitInput",25    "TableWidget",26    "TextArea",27    "TextInput",28    "TelInput",29    "TimeInput",30    "URLInput",31    "WeekInput",32)33 34 35def clean_key(key):36    key = key.rstrip("_")37    if key.startswith("data_") or key.startswith("aria_"):38        key = key.replace("_", "-")39    return key40 41 42def html_params(**kwargs):43    """44    Generate HTML attribute syntax from inputted keyword arguments.45 46    The output value is sorted by the passed keys, to provide consistent output47    each time this function is called with the same parameters. Because of the48    frequent use of the normally reserved keywords `class` and `for`, suffixing49    these with an underscore will allow them to be used.50 51    In order to facilitate the use of ``data-`` and ``aria-`` attributes, if the52    name of the attribute begins with ``data_`` or ``aria_``, then every53    underscore will be replaced with a hyphen in the generated attribute.54 55    >>> html_params(data_attr='user.name', aria_labeledby='name')56    'data-attr="user.name" aria-labeledby="name"'57 58    In addition, the values ``True`` and ``False`` are special:59      * ``attr=True`` generates the HTML compact output of a boolean attribute,60        e.g. ``checked=True`` will generate simply ``checked``61      * ``attr=False`` will be ignored and generate no output.62 63    >>> html_params(name='text1', id='f', class_='text')64    'class="text" id="f" name="text1"'65    >>> html_params(checked=True, readonly=False, name="text1", abc="hello")66    'abc="hello" checked name="text1"'67 68    .. versionchanged:: 3.069        ``aria_`` args convert underscores to hyphens like ``data_``70        args.71 72    .. versionchanged:: 2.273        ``data_`` args convert all underscores to hyphens, instead of74        only the first one.75    """76    params = []77    for k, v in sorted(kwargs.items()):78        k = clean_key(k)79        if v is True:80            params.append(k)81        elif v is False:82            pass83        else:84            params.append(f'{str(k)}="{escape(v)}"')  # noqa: B90785    return " ".join(params)86 87 88class ListWidget:89    """90    Renders a list of fields as a `ul` or `ol` list.91 92    This is used for fields which encapsulate many inner fields as subfields.93    The widget will try to iterate the field to get access to the subfields and94    call them to render them.95 96    If `prefix_label` is set, the subfield's label is printed before the field,97    otherwise afterwards. The latter is useful for iterating radios or98    checkboxes.99    """100 101    def __init__(self, html_tag="ul", prefix_label=True):102        assert html_tag in ("ol", "ul")103        self.html_tag = html_tag104        self.prefix_label = prefix_label105 106    def __call__(self, field, **kwargs):107        kwargs.setdefault("id", field.id)108        html = [f"<{self.html_tag} {html_params(**kwargs)}>"]109        for subfield in field:110            if self.prefix_label:111                html.append(f"<li>{subfield.label} {subfield()}</li>")112            else:113                html.append(f"<li>{subfield()} {subfield.label}</li>")114        html.append("</%s>" % self.html_tag)115        return Markup("".join(html))116 117 118class TableWidget:119    """120    Renders a list of fields as a set of table rows with th/td pairs.121 122    If `with_table_tag` is True, then an enclosing <table> is placed around the123    rows.124 125    Hidden fields will not be displayed with a row, instead the field will be126    pushed into a subsequent table row to ensure XHTML validity. Hidden fields127    at the end of the field list will appear outside the table.128    """129 130    def __init__(self, with_table_tag=True):131        self.with_table_tag = with_table_tag132 133    def __call__(self, field, **kwargs):134        html = []135        if self.with_table_tag:136            kwargs.setdefault("id", field.id)137            html.append("<table %s>" % html_params(**kwargs))138        hidden = ""139        for subfield in field:140            if subfield.type in ("HiddenField", "CSRFTokenField"):141                hidden += str(subfield)142            else:143                html.append(144                    "<tr><th>%s</th><td>%s%s</td></tr>"145                    % (str(subfield.label), hidden, str(subfield))146                )147                hidden = ""148        if self.with_table_tag:149            html.append("</table>")150        if hidden:151            html.append(hidden)152        return Markup("".join(html))153 154 155class Input:156    """157    Render a basic ``<input>`` field.158 159    This is used as the basis for most of the other input fields.160 161    By default, the `_value()` method will be called upon the associated field162    to provide the ``value=`` HTML attribute.163    """164 165    html_params = staticmethod(html_params)166    validation_attrs = ["required", "disabled"]167 168    def __init__(self, input_type=None):169        if input_type is not None:170            self.input_type = input_type171 172    def __call__(self, field, **kwargs):173        kwargs.setdefault("id", field.id)174        kwargs.setdefault("type", self.input_type)175        if "value" not in kwargs:176            kwargs["value"] = field._value()177        flags = getattr(field, "flags", {})178        for k in dir(flags):179            if k in self.validation_attrs and k not in kwargs:180                kwargs[k] = getattr(flags, k)181        return Markup("<input %s>" % self.html_params(name=field.name, **kwargs))182 183 184class TextInput(Input):185    """186    Render a single-line text input.187    """188 189    input_type = "text"190    validation_attrs = [191        "required",192        "disabled",193        "readonly",194        "maxlength",195        "minlength",196        "pattern",197    ]198 199 200class PasswordInput(Input):201    """202    Render a password input.203 204    For security purposes, this field will not reproduce the value on a form205    submit by default. To have the value filled in, set `hide_value` to206    `False`.207    """208 209    input_type = "password"210    validation_attrs = [211        "required",212        "disabled",213        "readonly",214        "maxlength",215        "minlength",216        "pattern",217    ]218 219    def __init__(self, hide_value=True):220        self.hide_value = hide_value221 222    def __call__(self, field, **kwargs):223        if self.hide_value:224            kwargs["value"] = ""225        return super().__call__(field, **kwargs)226 227 228class HiddenInput(Input):229    """230    Render a hidden input.231    """232 233    input_type = "hidden"234 235    def __init__(self, *args, **kwargs):236        super().__init__(*args, **kwargs)237        self.field_flags = {"hidden": True}238 239 240class CheckboxInput(Input):241    """242    Render a checkbox.243 244    The ``checked`` HTML attribute is set if the field's data is a non-false value.245    """246 247    input_type = "checkbox"248 249    def __call__(self, field, **kwargs):250        if getattr(field, "checked", field.data):251            kwargs["checked"] = True252        return super().__call__(field, **kwargs)253 254 255class RadioInput(Input):256    """257    Render a single radio button.258 259    This widget is most commonly used in conjunction with ListWidget or some260    other listing, as singular radio buttons are not very useful.261    """262 263    input_type = "radio"264 265    def __call__(self, field, **kwargs):266        if field.checked:267            kwargs["checked"] = True268        return super().__call__(field, **kwargs)269 270 271class FileInput(Input):272    """Render a file chooser input.273 274    :param multiple: allow choosing multiple files275    """276 277    input_type = "file"278    validation_attrs = ["required", "disabled", "accept"]279 280    def __init__(self, multiple=False):281        super().__init__()282        self.multiple = multiple283 284    def __call__(self, field, **kwargs):285        # browser ignores value of file input for security286        kwargs["value"] = False287 288        if self.multiple:289            kwargs["multiple"] = True290 291        return super().__call__(field, **kwargs)292 293 294class SubmitInput(Input):295    """296    Renders a submit button.297 298    The field's label is used as the text of the submit button instead of the299    data on the field.300    """301 302    input_type = "submit"303 304    def __call__(self, field, **kwargs):305        kwargs.setdefault("value", field.label.text)306        return super().__call__(field, **kwargs)307 308 309class TextArea:310    """311    Renders a multi-line text area.312 313    `rows` and `cols` ought to be passed as keyword args when rendering.314    """315 316    validation_attrs = ["required", "disabled", "readonly", "maxlength", "minlength"]317 318    def __call__(self, field, **kwargs):319        kwargs.setdefault("id", field.id)320        flags = getattr(field, "flags", {})321        for k in dir(flags):322            if k in self.validation_attrs and k not in kwargs:323                kwargs[k] = getattr(flags, k)324        return Markup(325            "<textarea %s>\r\n%s</textarea>"326            % (html_params(name=field.name, **kwargs), escape(field._value()))327        )328 329 330class Select:331    """332    Renders a select field.333 334    If `multiple` is True, then the `size` property should be specified on335    rendering to make the field useful.336 337    The field must provide an `iter_choices()` method which the widget will338    call on rendering; this method must yield tuples of339    `(value, label, selected)` or `(value, label, selected, render_kw)`.340    It also must provide a `has_groups()` method which tells whether choices341    are divided into groups, and if they do, the field must have an342    `iter_groups()` method that yields tuples of `(label, choices)`, where343    `choices` is a iterable of `(value, label, selected)` tuples.344    """345 346    validation_attrs = ["required", "disabled"]347 348    def __init__(self, multiple=False):349        self.multiple = multiple350 351    def __call__(self, field, **kwargs):352        kwargs.setdefault("id", field.id)353        if self.multiple:354            kwargs["multiple"] = True355        flags = getattr(field, "flags", {})356        for k in dir(flags):357            if k in self.validation_attrs and k not in kwargs:358                kwargs[k] = getattr(flags, k)359        html = ["<select %s>" % html_params(name=field.name, **kwargs)]360        if field.has_groups():361            for group, choices in field.iter_groups():362                html.append("<optgroup %s>" % html_params(label=group))363                for choice in choices:364                    if len(choice) == 4:365                        val, label, selected, render_kw = choice366                    else:367                        warnings.warn(368                            "'iter_groups' is expected to return 4 items tuple since "369                            "wtforms 3.1, this will be mandatory in wtforms 3.2",370                            DeprecationWarning,371                            stacklevel=2,372                        )373                        val, label, selected = choice374                        render_kw = {}375                    html.append(self.render_option(val, label, selected, **render_kw))376                html.append("</optgroup>")377        else:378            for choice in field.iter_choices():379                if len(choice) == 4:380                    val, label, selected, render_kw = choice381                else:382                    warnings.warn(383                        "'iter_groups' is expected to return 4 items tuple since "384                        "wtforms 3.1, this will be mandatory in wtforms 3.2",385                        DeprecationWarning,386                        stacklevel=2,387                    )388                    val, label, selected = choice389                    render_kw = {}390                html.append(self.render_option(val, label, selected, **render_kw))391        html.append("</select>")392        return Markup("".join(html))393 394    @classmethod395    def render_option(cls, value, label, selected, **kwargs):396        if value is True:397            # Handle the special case of a 'True' value.398            value = str(value)399 400        options = dict(kwargs, value=value)401        if selected:402            options["selected"] = True403        return Markup(f"<option {html_params(**options)}>{escape(label)}</option>")404 405 406class Option:407    """408    Renders the individual option from a select field.409 410    This is just a convenience for various custom rendering situations, and an411    option by itself does not constitute an entire field.412    """413 414    def __call__(self, field, **kwargs):415        return Select.render_option(416            field._value(), field.label.text, field.checked, **kwargs417        )418 419 420class SearchInput(Input):421    """422    Renders an input with type "search".423    """424 425    input_type = "search"426    validation_attrs = [427        "required",428        "disabled",429        "readonly",430        "maxlength",431        "minlength",432        "pattern",433    ]434 435 436class TelInput(Input):437    """438    Renders an input with type "tel".439    """440 441    input_type = "tel"442    validation_attrs = [443        "required",444        "disabled",445        "readonly",446        "maxlength",447        "minlength",448        "pattern",449    ]450 451 452class URLInput(Input):453    """454    Renders an input with type "url".455    """456 457    input_type = "url"458    validation_attrs = [459        "required",460        "disabled",461        "readonly",462        "maxlength",463        "minlength",464        "pattern",465    ]466 467 468class EmailInput(Input):469    """470    Renders an input with type "email".471    """472 473    input_type = "email"474    validation_attrs = [475        "required",476        "disabled",477        "readonly",478        "maxlength",479        "minlength",480        "pattern",481    ]482 483 484class DateTimeInput(Input):485    """486    Renders an input with type "datetime".487    """488 489    input_type = "datetime"490    validation_attrs = ["required", "disabled", "readonly", "max", "min", "step"]491 492 493class DateInput(Input):494    """495    Renders an input with type "date".496    """497 498    input_type = "date"499    validation_attrs = ["required", "disabled", "readonly", "max", "min", "step"]500 501 502class MonthInput(Input):503    """504    Renders an input with type "month".505    """506 507    input_type = "month"508    validation_attrs = ["required", "disabled", "readonly", "max", "min", "step"]509 510 511class WeekInput(Input):512    """513    Renders an input with type "week".514    """515 516    input_type = "week"517    validation_attrs = ["required", "disabled", "readonly", "max", "min", "step"]518 519 520class TimeInput(Input):521    """522    Renders an input with type "time".523    """524 525    input_type = "time"526    validation_attrs = ["required", "disabled", "readonly", "max", "min", "step"]527 528 529class DateTimeLocalInput(Input):530    """531    Renders an input with type "datetime-local".532    """533 534    input_type = "datetime-local"535    validation_attrs = ["required", "disabled", "readonly", "max", "min", "step"]536 537 538class NumberInput(Input):539    """540    Renders an input with type "number".541    """542 543    input_type = "number"544    validation_attrs = ["required", "disabled", "readonly", "max", "min", "step"]545 546    def __init__(self, step=None, min=None, max=None):547        self.step = step548        self.min = min549        self.max = max550 551    def __call__(self, field, **kwargs):552        if self.step is not None:553            kwargs.setdefault("step", self.step)554        if self.min is not None:555            kwargs.setdefault("min", self.min)556        if self.max is not None:557            kwargs.setdefault("max", self.max)558        return super().__call__(field, **kwargs)559 560 561class RangeInput(Input):562    """563    Renders an input with type "range".564    """565 566    input_type = "range"567    validation_attrs = ["required", "disabled", "max", "min", "step"]568 569    def __init__(self, step=None):570        self.step = step571 572    def __call__(self, field, **kwargs):573        if self.step is not None:574            kwargs.setdefault("step", self.step)575        return super().__call__(field, **kwargs)576 577 578class ColorInput(Input):579    """580    Renders an input with type "color".581    """582 583    input_type = "color"584 
codekingpro/portable-devtools · Team Ai