Cannot initialise a Choice field with an IContextSourceBinder source and a default value
Affects | Status | Importance | Assigned to | Milestone | |
---|---|---|---|---|---|
Zope 3 |
Fix Released
|
Undecided
|
Unassigned |
Bug Description
Let's say we have a context source binder:
>>> from zope.schema.
>>> from zope.interface import implements
>>> from zope.schema.
>>> class Binder(object):
... implements(
... def __call__(self, context):
... return SimpleVocabular
...
If we try to initialise a Choice field with this as a source and no default value, we're OK:
>>> from zope.schema import Choice
>>> field = Choice(
Note that the field can be validated against an item in the vocabulary only once bound:
>>> field.bind(
True
If the field is not bound, we get an error:
>>> field.validate(
Traceback (most recent call last):
File "<console>", line 1, in ?
File "/Users/
self.
File "/Users/
if value not in vocabulary:
TypeError: iterable argument required
This is because at this point, self.vocabulary is an IContextSourceB
Unfortunately, the default value is validated against an unbound field when initialised in the constructor, giving the same error:
>>> field = Choice(
Traceback (most recent call last):
File "<console>", line 1, in ?
File "/Users/
super(Choice, self)._
File "/Users/
self.default = default
File "/Users/
inst.
File "/Users/
self.
File "/Users/
if value not in vocabulary:
TypeError: iterable argument required
This means that it is impossible to initialise a choice field with a context source binder and a default. The choice field actually has a flag that it sets in the initialiser that "turns off" validation, but it is only used for named vocabularies:
# Before a default value is checked, it is validated. However, a
# named vocabulary is usually not complete when these fields are
# initialized. Therefore signal the validation method to ignore
# default value checks during initialization of a Choice tied to a
# registered vocabulary.
I think it should also be set if IContextSourceB
Of course, this means the default value isn't validated, but that's always going to be impossible anyway with a context-bound source, since the context isn't known at field initialisation time.
Fix committed in 97798.