def bind(self, object): """See zope.schema._bootstrapinterfaces.IField.""" clone = super(Choice, self).bind(object) # get registered vocabulary if needed: if IContextSourceBinder.providedBy(self.vocabulary): clone.vocabulary = self.vocabulary(object) assert ISource.providedBy(clone.vocabulary) elif clone.vocabulary is None and self.vocabularyName is not None: vr = getVocabularyRegistry() clone.vocabulary = vr.get(object, self.vocabularyName) assert ISource.providedBy(clone.vocabulary) return clone
def choicePersistentFieldAdapter(context): """Special handling for Choice fields. """ instance = persistentFieldAdapter(context) if instance is None: return None if ISource.providedBy(context.vocabulary) or \ IContextSourceBinder.providedBy(context.vocabulary): safe = False # Attempt to reverse engineer a 'values' argument if isinstance(context.vocabulary, SimpleVocabulary): values = [] safe = True for term in context.vocabulary: if term.token == str(term.value) and is_primitive(term.value): values.append(term.value) else: safe = False break if safe: instance._values = values if not safe: __traceback_info__ = "Persistent fields only support named vocabularies " + \ "or vocabularies based on simple value sets." return None return instance
def reply(self): if len(self.params) != 1: return self._error( 400, "Bad Request", "Must supply exactly one path parameter (fieldname)" ) fieldname = self.params[0] field = get_field_by_name(fieldname, self.context) if field is None: return self._error(404, "Not Found", "No such field: %r" % fieldname) bound_field = field.bind(self.context) source = bound_field.source if not ISource.providedBy(source): return self._error( 404, "Not Found", "Field %r does not have a source" % fieldname ) if not IIterableSource.providedBy(source): return self._error( 400, "Bad Request", "Source for field %r is not iterable. " % fieldname ) serializer = getMultiAdapter((source, self.request), interface=ISerializeToJson) return serializer( "{}/@sources/{}".format(self.context.absolute_url(), fieldname) )
def bound_source(self): if self._bound_source is None: source = self.source if IContextSourceBinder.providedBy(source): source = source(self.context) assert ISource.providedBy(source) # custom if IElephantVocabulary.providedBy(source): try: # If we cannot adapt the behavior or schema interface, # the context is wrong (e.g. we are one add form on the # parent). So we skip adding the current value. storage = self.field.interface(self.context) except TypeError: value = None else: value = getattr(storage, self.field.__name__) if value and value not in source.vocab: term = source.vocab.createTerm( value, value, value) source.vocab._terms.append(term) source.vocab.by_value[term.value] = term source.vocab.by_token[term.token] = term source.hidden_terms.append(value) # end custom self._bound_source = source return self._bound_source
def bound_source(self): if self._bound_source is None: source = self.source if IContextSourceBinder.providedBy(source): source = source(self.context) assert ISource.providedBy(source) # custom if IElephantVocabulary.providedBy(source): try: # If we cannot adapt the behavior or schema interface, # the context is wrong (e.g. we are one add form on the # parent). So we skip adding the current value. storage = self.field.interface(self.context) except TypeError: value = None else: value = getattr(storage, self.field.__name__) if value and value not in source.vocab: contact_info = getUtility(IContactInformation) term = source.vocab.createTerm( value, value, contact_info.describe(value)) source.vocab._terms.append(term) source.vocab.by_value[term.value] = term source.vocab.by_token[term.token] = term source.hidden_terms.append(value) # end custom self._bound_source = source return self._bound_source
def __init__(self, values=None, vocabulary=None, source=None, **kw): """Initialize object.""" if vocabulary is not None: assert (isinstance(vocabulary, string_types) or IBaseVocabulary.providedBy(vocabulary)) assert source is None, ( "You cannot specify both source and vocabulary.") elif source is not None: vocabulary = source assert not (values is None and vocabulary is None), ( "You must specify either values or vocabulary.") assert values is None or vocabulary is None, ( "You cannot specify both values and vocabulary.") self.vocabulary = None self.vocabularyName = None if values is not None: self.vocabulary = SimpleVocabulary.fromValues(values) elif isinstance(vocabulary, string_types): self.vocabularyName = vocabulary else: assert (ISource.providedBy(vocabulary) or IContextSourceBinder.providedBy(vocabulary)) self.vocabulary = vocabulary # 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. self._init_field = (bool(self.vocabularyName) or IContextSourceBinder.providedBy(self.vocabulary)) super(Choice, self).__init__(**kw) self._init_field = False
def __init__(self, values=None, vocabulary=None, source=None, **kw): """Initialize object.""" if vocabulary is not None: assert (isinstance(vocabulary, basestring) or IBaseVocabulary.providedBy(vocabulary)) assert source is None, ( "You cannot specify both source and vocabulary.") elif source is not None: vocabulary = source assert not (values is None and vocabulary is None), ( "You must specify either values or vocabulary.") assert values is None or vocabulary is None, ( "You cannot specify both values and vocabulary.") self.vocabulary = None self.vocabularyName = None if values is not None: self.vocabulary = SimpleVocabulary.fromValues(values) elif isinstance(vocabulary, (unicode, str)): self.vocabularyName = vocabulary else: assert (ISource.providedBy(vocabulary) or IContextSourceBinder.providedBy(vocabulary)) self.vocabulary = vocabulary # 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. self._init_field = (bool(self.vocabularyName) or IContextSourceBinder.providedBy(self.vocabulary)) super(Choice, self).__init__(**kw) self._init_field = False
def bound_source(self): if self._bound_source is None: source = self.source if IContextSourceBinder.providedBy(source): source = source(self.context) assert ISource.providedBy(source) self._bound_source = source return self._bound_source
def _constructField(self, attributes): if 'vocabulary' in attributes: try: component = resolve(attributes['vocabulary']) if IBaseVocabulary.providedBy(component): attributes['vocabulary'] = component elif (ISource.providedBy(component) or IContextSourceBinder.providedBy(component)): attributes['source'] = component del attributes['vocabulary'] except ImportError: # regular named vocabulary, leave as is pass return super(QueryChoiceHandler, self)._constructField(attributes)
def import_node(self, interface, child): """Import a single <property /> node """ property_name = child.getAttribute('name') field = interface.get(property_name, None) if field is None: return field = field.bind(self.assignment) value = None # If we have a collection, we need to look at the value_type. # We look for <element>value</element> child nodes and get the # value from there if ICollection.providedBy(field): value_type = field.value_type value = [] for element in child.childNodes: if element.nodeName != 'element': continue element_value = self.extract_text(element) value.append(self.from_unicode(value_type, element_value)) value = self.field_typecast(field, value) # Otherwise, just get the value of the <property /> node else: value = self.extract_text(child) if not (field.getName() == 'root' and value in ['', '/']): value = self.from_unicode(field, value) if field.getName() == 'root' and value in ['', '/']: # these valid values don't pass validation of SearchableTextSourceBinder field.set(self.assignment, value) else: # I don't care if it's raised on a path... try: field.validate(value) except ConstraintNotSatisfied: if type(field) == Choice and ISource.providedBy(field.source): pass else: raise field.set(self.assignment, value)
def from_unicode(self, field, value): import zope.schema if IFromUnicode.providedBy(field) or \ isinstance(field, zope.schema.Bool): if type(field) == zope.schema.Int and len(value) == 0: return None try: return field.fromUnicode(value) except ConstraintNotSatisfied: if type(field) == Choice and \ ISource.providedBy(field.source): if value in self._already_raised: return value else: self._already_raised.append(value) raise MissingObjectException(value) raise else: return self.field_typecast(field, value)
def __init__(self, values=None, vocabulary=None, source=None, **kw): """Initialize object.""" if vocabulary is not None: if (not isinstance(vocabulary, string_types) and not IBaseVocabulary.providedBy(vocabulary)): raise ValueError('vocabulary must be a string or implement ' 'IBaseVocabulary') if source is not None: raise ValueError( "You cannot specify both source and vocabulary.") elif source is not None: vocabulary = source if (values is None and vocabulary is None): raise ValueError( "You must specify either values or vocabulary." ) if values is not None and vocabulary is not None: raise ValueError( "You cannot specify both values and vocabulary." ) self.vocabulary = None self.vocabularyName = None if values is not None: self.vocabulary = SimpleVocabulary.fromValues(values) elif isinstance(vocabulary, string_types): self.vocabularyName = vocabulary else: if (not ISource.providedBy(vocabulary) and not IContextSourceBinder.providedBy(vocabulary)): raise ValueError('Invalid vocabulary') self.vocabulary = vocabulary # 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. self._init_field = (bool(self.vocabularyName) or IContextSourceBinder.providedBy(self.vocabulary)) super(Choice, self).__init__(**kw) self._init_field = False
def _resolve_vocabulary(self, value): # Find the vocabulary we should use, raising # an exception if this isn't possible, and returning # an ISource otherwise. vocabulary = self.vocabulary if IContextSourceBinder.providedBy(vocabulary) and self.context is not None: vocabulary = vocabulary(self.context) elif vocabulary is None and self.vocabularyName is not None: vr = getVocabularyRegistry() try: vocabulary = vr.get(self.context, self.vocabularyName) except LookupError: raise MissingVocabularyError( "Can't validate value without vocabulary named %r" % (self.vocabularyName,) ).with_field_and_value(self, value) if not ISource.providedBy(vocabulary): raise InvalidVocabularyError(vocabulary).with_field_and_value(self, value) return vocabulary
def reply(self): if len(self.params) not in (1, 2): return self._error( 400, "Bad Request", "Must supply either one (fieldname) or two (portal_type, fieldname) parameters" ) if len(self.params) == 1: # Edit intent # - context is the object to be edited # - schemata need to be determined via context self.intent = 'edit' portal_type = None fieldname = self.params[0] schemata = iterSchemata(self.context) else: # Add intent # - context is the container where the object will be created # - portal_type is the type of object to be created # - schemata need to be determined via portal_type self.intent = 'add' portal_type = self.params[0] fieldname = self.params[1] schemata = iterSchemataForType(portal_type) alsoProvides(self.request, IDuringContentCreation) field = get_field_by_name(fieldname, schemata) if field is None: return self._error(404, "Not Found", "No such field: %r" % fieldname) bound_field = field.bind(self.context) # Look for a source directly on the field first source = getattr(bound_field, 'source', None) # Handle ICollections (like Tuples, Lists and Sets). These don't have # sources themselves, but instead are multivalued, and their # items are backed by a value_type of Choice with a source if ICollection.providedBy(bound_field): source = self._get_value_type_source(bound_field) if not source: ftype = bound_field.__class__.__name__ return self._error( 404, "Not Found", "%r Field %r does not have a value_type of Choice with " "an ISource" % (ftype, fieldname)) if not ISource.providedBy(source): return self._error(404, "Not Found", "Field %r does not have a source" % fieldname) if not IIterableSource.providedBy(source): return self._error( 400, "Bad Request", "Source for field %r is not iterable. " % fieldname) serializer = getMultiAdapter((source, self.request), interface=ISerializeToJson) return serializer("{}/@sources/{}".format(self.context.absolute_url(), fieldname))