kvesteri/wtforms-components

SelectField & SelectMultipleField dynamic choices raising error on WTForms >= 2.3.0

sethkaufee opened this issue · 0 comments

First off, thank you for publishing this package. Appreciate the responses and issue closing recently.

With the recent WTForms update, any lambda or other values that cannot be coerced to a list will fail on initialization since the new SelectField now copies the value with list(choices). Before, the values were being copied using the copy library, copy(choices). To support callables (https://wtforms-components.readthedocs.io/en/latest/#selectfield-selectmultiplefield) in the new version, it looks like the __init__ might have to be overridden to continue to support dynamic choices.

I'm not sure how much the will hurt backwards compatibility but version 2.2.1 looks like:

    def __init__(self, label=None, validators=None, coerce=text_type, choices=None, **kwargs):
        super(SelectField, self).__init__(label, validators, **kwargs)
        self.coerce = coerce
        self.choices = copy(choices)

and the new looks like:

    def __init__(
        self,
        label=None,
        validators=None,
        coerce=str,
        choices=None,
        validate_choice=True,
        **kwargs,
    ):
        super().__init__(label, validators, **kwargs)
        self.coerce = coerce
        self.choices = list(choices) if choices is not None else None
        self.validate_choice = validate_choice

Deferring the choices initialization might cover most bases (although haven't ran the code):

class SelectField(_SelectField):
    def __init__(self, *args, choices=None, **kwargs):
        if callable(choices):
            super().__init__(*args, **kwargs)
            self.choices = copy(choices)
        else:
            super().__init__(*args, choices=choices, **kwargs)

I would be happy to open a PR on this or work on another solution if you have one. Thanks again!