Example #1
0
    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
Example #2
0
    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
Example #3
0
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
Example #4
0
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
Example #5
0
    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)
        )
Example #6
0
    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
Example #8
0
    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
Example #9
0
    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
Example #10
0
 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
Example #11
0
 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
Example #12
0
 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)
Example #13
0
    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)
Example #14
0
    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)
Example #15
0
 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)
Example #16
0
 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)
Example #17
0
    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
Example #18
0
    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
Example #19
0
    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))