from inspect import getmembers
from wtforms.validators import DataRequired
from onegov.form.fields import UploadField
from onegov.form.validators import StrictOptional
from typing import overload, Any, Literal, TypeVar, TYPE_CHECKING
if TYPE_CHECKING:
from collections.abc import Collection, Iterator
from onegov.form import Form
from typing import TypeGuard
from wtforms.fields.core import UnboundField
[docs]
def prepare_for_submission(
form_class: type[_FormT],
for_change_request: bool = False,
force_simple: bool = True,
) -> type[_FormT]:
# force all upload fields to be simple, we do not support the more
# complex add/keep/replace widget, which is hard to properly support
# and is not super useful in submissions
def is_upload(attribute: object) -> 'TypeGuard[UnboundField[UploadField]]':
if not hasattr(attribute, 'field_class'):
return False
return issubclass(attribute.field_class, UploadField)
for name, field in getmembers(form_class, predicate=is_upload):
if force_simple:
if 'render_kw' not in field.kwargs:
field.kwargs['render_kw'] = {}
field.kwargs['render_kw']['force_simple'] = True
# Otherwise the user gets stuck when in form validation not
# changing the file
if for_change_request:
validators = [StrictOptional()] + [
v for v in field.kwargs['validators'] or []
if not isinstance(v, DataRequired)
]
field.kwargs['validators'] = validators
return form_class
@overload
[docs]
def get_fields(
form_class: type['Form'],
names_only: Literal[False] = False,
exclude: 'Collection[str] | None' = None
) -> 'Iterator[tuple[str, UnboundField[Any]]]': ...
@overload
def get_fields(
form_class: type['Form'],
names_only: Literal[True],
exclude: 'Collection[str] | None' = None
) -> 'Iterator[str]': ...
def get_fields(
form_class: type['Form'],
names_only: bool = False,
exclude: 'Collection[str] | None' = None
) -> 'Iterator[str | tuple[str, UnboundField[Any]]]':
""" Takes an unbound form and returns the name of the fields """
def is_field(attribute: object) -> 'TypeGuard[UnboundField[Any]]':
return hasattr(attribute, 'field_class')
for name, field in getmembers(form_class, predicate=is_field):
if exclude and name in exclude:
continue
if names_only:
yield name
else:
yield name, field