Пример #1
0
    def __get__(self, inst, klass):
        if inst is None:
            return self

        attribute = getattr(inst.context, self._get_name, _marker)
        if attribute is _marker:
            field = self._field.bind(inst)
            attribute = getattr(field, 'default', _marker)
            if attribute is _marker:
                raise AttributeError(self._field.__name__)
        elif callable(attribute):
            attribute = attribute()

        if isinstance(attribute, DateTime):
            # Ensure datetime value is stripped of any timezone and seconds
            # so that it can be compared with the value returned by the widget
            return datetime(*map(int, attribute.parts()[:6]))

        if attribute is None:
            return

        if IText.providedBy(self._field):
            return attribute.decode('utf-8')

        if ISequence.providedBy(self._field):
            if IText.providedBy(self._field.value_type):
                return type(attribute)(item.decode('utf-8')
                                       for item in attribute)

        return attribute
Пример #2
0
    def __set__(self, inst, value):
        field = self._field.bind(inst)
        field.validate(value)
        if field.readonly:
            raise ValueError(self._field.__name__, 'field is readonly')
        if isinstance(value, datetime):
            # The ensures that the converted DateTime value is in the
            # server's local timezone rather than GMT.
            value = DateTime(value.year, value.month, value.day,
                             value.hour, value.minute)
        elif value is not None:
            if IText.providedBy(self._field):
                value = value.encode('utf-8')

            elif ISequence.providedBy(self._field):
                if IText.providedBy(self._field.value_type):
                    value = type(value)(
                        item.encode('utf-8') for item in value
                    )

        if self._set_name:
            getattr(inst.context, self._set_name)(value)
        elif inst.context.hasProperty(self._get_name):
            inst.context._updateProperty(self._get_name, value)
        else:
            setattr(inst.context, self._get_name, value)
Пример #3
0
    def __set__(self, inst, value):
        field = self._field.bind(inst)
        field.validate(value)
        if field.readonly:
            raise ValueError(self._field.__name__, 'field is readonly')
        if isinstance(value, datetime):
            # The ensures that the converted DateTime value is in the
            # server's local timezone rather than GMT.
            value = DateTime(value.year, value.month, value.day,
                             value.hour, value.minute)
        elif value is not None:
            if IText.providedBy(self._field):
                value = value.encode('utf-8')

            elif ISequence.providedBy(self._field):
                if IText.providedBy(self._field.value_type):
                    value = type(value)(
                        item.encode('utf-8') for item in value
                    )

        if self._set_name:
            getattr(inst.context, self._set_name)(value)
        elif inst.context.hasProperty(self._get_name):
            inst.context._updateProperty(self._get_name, value)
        else:
            setattr(inst.context, self._get_name, value)
Пример #4
0
    def __get__(self, inst, klass):
        if inst is None:
            return self

        attribute = getattr(inst.context, self._get_name, _marker)
        if attribute is _marker:
            field = self._field.bind(inst)
            attribute = getattr(field, 'default', _marker)
            if attribute is _marker:
                raise AttributeError(self._field.__name__)
        elif callable(attribute):
            attribute = attribute()

        if isinstance(attribute, DateTime):
            # Ensure datetime value is stripped of any timezone and seconds
            # so that it can be compared with the value returned by the widget
            return datetime(*map(int, attribute.parts()[:6]))

        if attribute is None:
            return

        if IText.providedBy(self._field):
            return attribute.decode('utf-8')

        if ISequence.providedBy(self._field):
            if IText.providedBy(self._field.value_type):
                return type(attribute)(
                    item.decode('utf-8') for item in attribute
                )

        return attribute
Пример #5
0
def encode(data, schema, ignore=()):
    """Given a data dictionary with key/value pairs and schema, return an
    encoded query string. This is similar to urllib.urlencode(), but field
    names will include the appropriate field type converters, e.g. an int
    field will be encoded as fieldname:int=123. Fields not found in the data
    dict will be ignored, and items in the dict not in the schema will also
    be ignored. Additional fields to ignore can be passed with the 'ignore'
    parameter. If any fields cannot be converted, a ComponentLookupError
    will be raised.
    """

    encode = []

    for name, field in getFieldsInOrder(schema):
        if name in ignore or name not in data:
            continue

        converter = IFieldTypeConverter(field, None)
        if converter is None:
            raise ComponentLookupError(u"Cannot URL encode %s of type %s" % (
                name, field.__class__,))

        encoded_name = name
        if converter.token:
            encoded_name = "%s:%s" % (name, converter.token,)

        value = data[name]
        if value is None:
            continue

        if ISequence.providedBy(field):
            value_type_converter = IFieldTypeConverter(field.value_type, None)
            if value_type_converter is None:
                raise ComponentLookupError(u"Cannot URL encode value type "
                    u"for %s of type %s : %s" % (
                        name, field.__class__, field.value_type.__class__,))

            if value_type_converter.token:
                encoded_name = "%s:%s:%s" % (
                    name, value_type_converter.token, converter.token,)

            for item in value:

                if isinstance(item, bool):
                    item = item and '1' or ''

                encode.append((encoded_name, item,))

        else:
            # The :bool converter just does bool() value, but urlencode() does
            # str() on the object. The result is False => 'False' => True :(
            if isinstance(value, bool):
                value = value and '1' or ''

            encode.append((encoded_name, value))

    return urllib.urlencode(encode)
Пример #6
0
def decode(data, schema, missing=True):
    """Decode a data dict according to a schema. The returned dictionary will
    contain only keys matching schema names, and will force type values
    appropriately.

    This function is only necessary because the encoders used by encode()
    are not sufficiently detailed to always return the exact type expected
    by a field, e.g. resulting in ascii/unicode discrepancies.

    If missing is True, fields that are in the schema but not in the data will
    be set to field.missing_value. Otherwise, they are ignored.
    """

    decoded = {}

    for name, field in getFields(schema).items():
        if name not in data:
            if missing:
                decoded[name] = field.missing_value
            continue

        value = data[name]
        if value is None:
            continue

        field_type = field._type
        if isinstance(field_type, (tuple, list,)):
            field_type = field_type[-1]

        if ISequence.providedBy(field):
            converted = []

            value_type_field_type = field.value_type._type
            if isinstance(value_type_field_type, (tuple, list,)):
                value_type_field_type = value_type_field_type[-1]

            for item in value:
                if isinstance(item, str):
                    value = unicode(item, 'utf-8')
                if field.value_type._type and not isinstance(
                        item, field.value_type._type):
                    item = value_type_field_type(item)
                converted.append(item)

            value = converted
        elif isinstance(value, (tuple, list)) and value:
            value = value[0]

        if isinstance(value, str):
            value = unicode(value, 'utf-8')

        if field._type is not None and not isinstance(value, field._type):
            value = field_type(value)

        decoded[name] = value

    return decoded
Пример #7
0
def encode(data, schema, ignore=()):
    """Given a data dictionary with key/value pairs and schema, return an
    encoded query string. This is similar to urllib.urlencode(), but field
    names will include the appropriate field type converters, e.g. an int
    field will be encoded as fieldname:int=123. Fields not found in the data
    dict will be ignored, and items in the dict not in the schema will also
    be ignored. Additional fields to ignore can be passed with the 'ignore'
    parameter. If any fields cannot be converted, a ComponentLookupError
    will be raised.
    """

    encode = []

    for name, field in getFieldsInOrder(schema):
        if name in ignore or name not in data:
            continue

        converter = IFieldTypeConverter(field, None)
        if converter is None:
            raise ComponentLookupError(u"Cannot URL encode %s of type %s" % (
                name, field.__class__,))

        encoded_name = name
        if converter.token:
            encoded_name = "%s:%s" % (name, converter.token,)

        value = data[name]
        if value is None:
            continue

        if ISequence.providedBy(field):
            value_type_converter = IFieldTypeConverter(field.value_type, None)
            if value_type_converter is None:
                raise ComponentLookupError(
                    u"Cannot URL encode value type for %s of type %s : %s" % (
                        name, field.__class__, field.value_type.__class__,))

            if value_type_converter.token:
                encoded_name = "%s:%s:%s" % (
                    name, value_type_converter.token, converter.token,)

            for item in value:

                if isinstance(item, bool):
                    item = item and '1' or ''

                encode.append((encoded_name, item,))

        else:
            # The :bool converter just does bool() value, but urlencode() does
            # str() on the object. The result is False => 'False' => True :(
            if isinstance(value, bool):
                value = value and '1' or ''

            encode.append((encoded_name, value))

    return urllib.urlencode(encode)
Пример #8
0
    def _base_args(self):
        """Method which will calculate _base class arguments.

        Returns (as python dictionary):
            - `pattern`: pattern name
            - `pattern_options`: pattern options
            - `name`: field name
            - `value`: field value

        :returns: Arguments which will be passed to _base
        :rtype: dict
        """
        args = super(AjaxSelectWidget, self)._base_args()
        args['name'] = self.name
        args['value'] = self.value
        args.setdefault('pattern_options', {})
        context = self.context
        field = None

        if IChoice.providedBy(self.field):
            args['pattern_options']['maximumSelectionSize'] = 1
            field = self.field
        elif ICollection.providedBy(self.field):
            field = self.field.value_type
        if IChoice.providedBy(field):
            args['pattern_options']['allowNewItems'] = 'false'

        args['pattern_options'] = dict_merge(self._ajaxselect_options(),
                                             args['pattern_options'])

        if field and getattr(field, 'vocabulary', None):
            form_url = self.request.getURL()
            source_url = '{0:s}/++widget++{1:s}/@@getSource'.format(
                form_url,
                self.name,
            )
            args['pattern_options']['vocabularyUrl'] = source_url

        # ISequence represents an orderable collection
        if ISequence.providedBy(self.field) or self.orderable:
            args['pattern_options']['orderable'] = True

        if self.vocabulary == 'plone.app.vocabularies.Keywords':
            membership = getToolByName(context, 'portal_membership')
            user = membership.getAuthenticatedMember()

            registry = getUtility(IRegistry)
            roles_allowed_to_add_keywords = registry.get(
                'plone.roles_allowed_to_add_keywords', set())
            roles = set(user.getRolesInContext(context))
            allowNewItems = bool(
                roles.intersection(roles_allowed_to_add_keywords), )
            args['pattern_options']['allowNewItems'] = str(
                allowNewItems, ).lower()

        return args
Пример #9
0
    def _base_args(self):
        """Method which will calculate _base class arguments.

        Returns (as python dictionary):
            - `pattern`: pattern name
            - `pattern_options`: pattern options
            - `name`: field name
            - `value`: field value
            - `multiple`: field multiple
            - `items`: field items from which we can select to

        :returns: Arguments which will be passed to _base
        :rtype: dict
        """
        args = super(SelectWidget, self)._base_args()
        args['name'] = self.name
        args['value'] = self.value
        args['multiple'] = self.multiple

        self.required = self.field.required

        options = args.setdefault('pattern_options', {})
        if self.multiple or ICollection.providedBy(self.field):
            options['multiple'] = args['multiple'] = self.multiple = True

        # ISequence represents an orderable collection
        if ISequence.providedBy(self.field) or self.orderable:
            options['orderable'] = True

        if self.multiple:
            options['separator'] = self.separator

        # Allow to clear field value if it is not required
        if not self.required:
            options['allowClear'] = True

        base_items = self.items
        if callable(base_items):
            # items used to be a property in all widgets, then in the select
            # widget it became a method, then in a few others too, but never in
            # all, so this was reverted to let it be a property again.  Let's
            # support both here to avoid breaking on some z3c.form versions.
            # See https://github.com/zopefoundation/z3c.form/issues/44
            base_items = base_items()
        items = []
        for item in base_items:
            if not isinstance(item['content'], basestring):
                item['content'] = translate(
                    item['content'],
                    context=self.request,
                    default=item['value'])
            items.append((item['value'], item['content']))
        args['items'] = items

        return args
Пример #10
0
    def _base_args(self):
        """Method which will calculate _base class arguments.

        Returns (as python dictionary):
            - `pattern`: pattern name
            - `pattern_options`: pattern options
            - `name`: field name
            - `value`: field value
            - `multiple`: field multiple
            - `items`: field items from which we can select to

        :returns: Arguments which will be passed to _base
        :rtype: dict
        """
        args = super(SelectWidget, self)._base_args()
        args['name'] = self.name
        args['value'] = self.value
        args['multiple'] = self.multiple

        self.required = self.field.required

        options = args.setdefault('pattern_options', {})
        if self.multiple or ICollection.providedBy(self.field):
            options['multiple'] = args['multiple'] = self.multiple = True

        # ISequence represents an orderable collection
        if ISequence.providedBy(self.field) or self.orderable:
            options['orderable'] = True

        if self.multiple:
            options['separator'] = self.separator

        # Allow to clear field value if it is not required
        if not self.required:
            options['allowClear'] = True

        base_items = self.items
        if callable(base_items):
            # items used to be a property in all widgets, then in the select
            # widget it became a method, then in a few others too, but never in
            # all, so this was reverted to let it be a property again.  Let's
            # support both here to avoid breaking on some z3c.form versions.
            # See https://github.com/zopefoundation/z3c.form/issues/44
            base_items = base_items()
        items = []
        for item in base_items:
            if not isinstance(item['content'], six.string_types):
                item['content'] = translate(item['content'],
                                            context=self.request,
                                            default=item['value'])
            items.append((item['value'], item['content']))
        args['items'] = items

        return args
Пример #11
0
    def _base_args(self):
        """Method which will calculate _base class arguments.

        Returns (as python dictionary):
            - `pattern`: pattern name
            - `pattern_options`: pattern options
            - `name`: field name
            - `value`: field value

        :returns: Arguments which will be passed to _base
        :rtype: dict
        """

        args = super(AjaxSelectWidget, self)._base_args()

        args["name"] = self.name
        args["value"] = self.value

        args.setdefault("pattern_options", {})

        field_name = self.field and self.field.__name__ or None

        context = self.context
        # We need special handling for AddForms
        if IAddForm.providedBy(getattr(self, "form")):
            context = self.form

        vocabulary_name = self.vocabulary
        field = None
        if IChoice.providedBy(self.field):
            args["pattern_options"]["maximumSelectionSize"] = 1
            field = self.field
        elif ICollection.providedBy(self.field):
            field = self.field.value_type
        if not vocabulary_name and field is not None:
            vocabulary_name = field.vocabularyName

        args["pattern_options"] = dict_merge(
            get_ajaxselect_options(
                context, args["value"], self.separator, vocabulary_name, self.vocabulary_view, field_name
            ),
            args["pattern_options"],
        )

        if field and getattr(field, "vocabulary", None):
            form_url = self.request.getURL()
            source_url = "%s/++widget++%s/@@getSource" % (form_url, self.name)
            args["pattern_options"]["vocabularyUrl"] = source_url

        # ISequence represents an orderable collection
        if ISequence.providedBy(self.field) or self.orderable:
            args["pattern_options"]["orderable"] = True

        return args
Пример #12
0
    def _base_args(self):
        """Method which will calculate _base class arguments.

        Returns (as python dictionary):
            - `pattern`: pattern name
            - `pattern_options`: pattern options
            - `name`: field name
            - `value`: field value

        :returns: Arguments which will be passed to _base
        :rtype: dict
        """

        args = super(AjaxSelectWidget, self)._base_args()

        args['name'] = self.name
        args['value'] = self.value

        args.setdefault('pattern_options', {})

        field_name = self.field and self.field.__name__ or None

        context = self.context
        # We need special handling for AddForms
        if IAddForm.providedBy(getattr(self, 'form')):
            context = self.form

        vocabulary_name = self.vocabulary
        field = None
        if IChoice.providedBy(self.field):
            args['pattern_options']['maximumSelectionSize'] = 1
            field = self.field
        elif ICollection.providedBy(self.field):
            field = self.field.value_type
        if not vocabulary_name and field is not None:
            vocabulary_name = field.vocabularyName

        args['pattern_options'] = dict_merge(
            get_ajaxselect_options(context, args['value'], self.separator,
                                   vocabulary_name, self.vocabulary_view,
                                   field_name),
            args['pattern_options'])

        if field and getattr(field, 'vocabulary', None):
            form_url = self.request.getURL()
            source_url = "%s/++widget++%s/@@getSource" % (form_url, self.name)
            args['pattern_options']['vocabularyUrl'] = source_url

        # ISequence represents an orderable collection
        if ISequence.providedBy(self.field) or self.orderable:
            args['pattern_options']['orderable'] = True

        return args
Пример #13
0
    def _base_args(self):
        """Method which will calculate _base class arguments.

        Returns (as python dictionary):
            - `pattern`: pattern name
            - `pattern_options`: pattern options
            - `name`: field name
            - `value`: field value
            - `multiple`: field multiple
            - `items`: field items from which we can select to

        :returns: Arguments which will be passed to _base
        :rtype: dict
        """
        args = super(SelectWidget, self)._base_args()
        args['name'] = self.name
        args['value'] = self.value
        args['multiple'] = self.multiple

        self.required = self.field.required

        options = args.setdefault('pattern_options', {})
        if self.multiple or ICollection.providedBy(self.field):
            options['multiple'] = args['multiple'] = self.multiple = True

        # ISequence represents an orderable collection
        if ISequence.providedBy(self.field) or self.orderable:
            options['orderable'] = True

        if self.multiple:
            options['separator'] = self.separator

        # Allow to clear field value if it is not required
        if not self.required:
            options['allowClear'] = True

        items = []
        for item in self.items():
            if not isinstance(item['content'], basestring):
                item['content'] = translate(
                    item['content'],
                    context=self.request,
                    default=item['value'])
            items.append((item['value'], item['content']))
        args['items'] = items

        return args
Пример #14
0
    def _base_args(self):
        """Method which will calculate _base class arguments.

        Returns (as python dictionary):
            - `pattern`: pattern name
            - `pattern_options`: pattern options
            - `name`: field name
            - `value`: field value
            - `multiple`: field multiple
            - `items`: field items from which we can select to

        :returns: Arguments which will be passed to _base
        :rtype: dict
        """
        args = super(SelectWidget, self)._base_args()
        args['name'] = self.name
        args['value'] = self.value
        args['multiple'] = self.multiple

        self.required = self.field.required

        options = args.setdefault('pattern_options', {})
        if self.multiple or ICollection.providedBy(self.field):
            options['multiple'] = args['multiple'] = self.multiple = True

        # ISequence represents an orderable collection
        if ISequence.providedBy(self.field) or self.orderable:
            options['orderable'] = True

        if self.multiple:
            options['separator'] = self.separator

        # Allow to clear field value if it is not required
        if not self.required:
            options['allowClear'] = True

        items = []
        for item in self.items():
            if not isinstance(item['content'], basestring):
                item['content'] = translate(
                    item['content'],
                    context=self.request,
                    default=item['value'])
            items.append((item['value'], item['content']))
        args['items'] = items

        return args
Пример #15
0
    def _base_args(self):
        """Method which will calculate _base class arguments.

        Returns (as python dictionary):
            - `pattern`: pattern name
            - `pattern_options`: pattern options
            - `name`: field name
            - `value`: field value
            - `multiple`: field multiple
            - `items`: field items from which we can select to

        :returns: Arguments which will be passed to _base
        :rtype: dict
        """
        args = super(SelectWidget, self)._base_args()
        args["name"] = self.name
        args["value"] = self.value
        args["multiple"] = self.multiple

        items = []
        for item in self.items():
            if not isinstance(item["content"], basestring):
                item["content"] = translate(item["content"], context=self.request, default=item["value"])
            items.append((item["value"], item["content"]))
        args["items"] = items

        options = args.setdefault("pattern_options", {})
        if self.multiple or ICollection.providedBy(self.field):
            options["multiple"] = args["multiple"] = self.multiple = True

        # ISequence represents an orderable collection
        if ISequence.providedBy(self.field) or self.orderable:
            options["orderable"] = True

        if self.multiple:
            options["separator"] = self.separator

        return args
Пример #16
0
    def _base_args(self):
        """Method which will calculate _base class arguments.

        Returns (as python dictionary):
            - `pattern`: pattern name
            - `pattern_options`: pattern options
            - `name`: field name
            - `value`: field value

        :returns: Arguments which will be passed to _base
        :rtype: dict
        """

        args = super(AjaxSelectWidget, self)._base_args()

        args['name'] = self.name
        args['value'] = self.value

        args.setdefault('pattern_options', {})

        field_name = self.field and self.field.__name__ or None

        context = self.context
        # We need special handling for AddForms
        if IAddForm.providedBy(getattr(self, 'form')):
            context = self.form

        args['pattern_options'] = dict_merge(
            get_ajaxselect_options(context, args['value'], self.separator,
                                   self.vocabulary, self.vocabulary_view,
                                   field_name),
            args['pattern_options'])

        # ISequence represents an orderable collection
        if ISequence.providedBy(self.field) or self.orderable:
            args['pattern_options']['orderable'] = True

        return args
Пример #17
0
def encode(data, schema, ignore=()):
    """Given a data dictionary with key/value pairs and schema, return an
    encoded query string. This is similar to urllib.urlencode(), but field
    names will include the appropriate field type converters, e.g. an int
    field will be encoded as fieldname:int=123. Fields not found in the data
    dict will be ignored, and items in the dict not in the schema will also
    be ignored. Additional fields to ignore can be passed with the 'ignore'
    parameter. If any fields cannot be converted, a ComponentLookupError
    will be raised.
    """

    encode = []

    for name, field in getFieldsInOrder(schema):
        if HAS_RFC822 and IPrimaryField.providedBy(field):
            continue

        if name in ignore or name not in data:
            continue

        converter = IFieldTypeConverter(field, None)
        if converter is None:
            raise ComponentLookupError(
                u'Cannot URL encode {0} of type {1}'.format(
                    name,
                    field.__class__
                )
            )

        encoded_name = name
        if converter.token:
            encoded_name = ':'.join([name, converter.token])

        value = data[name]
        if value is None:
            continue
        elif isinstance(value, six.text_type):
            value = value.encode('utf-8')

        if ISequence.providedBy(field):
            value_type_converter = IFieldTypeConverter(field.value_type, None)
            if value_type_converter is None:
                raise ComponentLookupError(
                    u'Cannot URL encode value type for {0} of type '
                    u'{1} : {2}'.format(
                        name,
                        field.__class__,
                        field.value_type.__class__
                    )
                )

            if value_type_converter.token:
                encoded_name = ':'.join([
                    name,
                    value_type_converter.token,
                    converter.token
                ])

            for item in value:

                if isinstance(item, bool):
                    item = item and '1' or ''
                elif isinstance(item, six.text_type):
                    item = item.encode('utf-8')

                if isinstance(item, dict):
                    encode.extend(map_to_pairs(encoded_name, item))
                else:
                    encode.append((encoded_name, item,))

        else:
            # The :bool converter just does bool() value, but urlencode() does
            # str() on the object. The result is False => 'False' => True :(
            if isinstance(value, bool):
                value = value and '1' or ''

            if isinstance(value, dict):
                encode.extend(map_to_pairs(encoded_name, value))
            else:
                encode.append((encoded_name, value))

    return parse.urlencode(encode)
Пример #18
0
 def testImplements(self):
     field = List()
     self.failUnless(IList.providedBy(field))
     self.failUnless(ISequence.providedBy(field))
     self.failUnless(ICollection.providedBy(field))
Пример #19
0
 def testImplements(self):
     field = List()
     self.assertTrue(IList.providedBy(field))
     self.assertTrue(ISequence.providedBy(field))
     self.assertTrue(ICollection.providedBy(field))
Пример #20
0
    def _base_args(self):
        """Method which will calculate _base class arguments.

        Returns (as python dictionary):
            - `pattern`: pattern name
            - `pattern_options`: pattern options
            - `name`: field name
            - `value`: field value

        :returns: Arguments which will be passed to _base
        :rtype: dict
        """

        args = super(AjaxSelectWidget, self)._base_args()

        args['name'] = self.name
        args['value'] = self.value

        args.setdefault('pattern_options', {})

        field_name = self.field and self.field.__name__ or None

        context = self.context
        view_context = get_widget_form(self)
        # For EditForms and non-Forms (in tests), the vocabulary is looked
        # up on the context, otherwise on the view
        if (IEditForm.providedBy(view_context)
                or not IForm.providedBy(view_context)):
            view_context = context

        vocabulary_name = self.vocabulary
        field = None
        if IChoice.providedBy(self.field):
            args['pattern_options']['maximumSelectionSize'] = 1
            field = self.field
        elif ICollection.providedBy(self.field):
            field = self.field.value_type
        if IChoice.providedBy(field):
            args['pattern_options']['allowNewItems'] = 'false'

        args['pattern_options'] = dict_merge(
            get_ajaxselect_options(view_context, args['value'], self.separator,
                                   vocabulary_name, self.vocabulary_view,
                                   field_name), args['pattern_options'])

        if field and getattr(field, 'vocabulary', None):
            form_url = self.request.getURL()
            source_url = '{0:s}/++widget++{1:s}/@@getSource'.format(
                form_url,
                self.name,
            )
            args['pattern_options']['vocabularyUrl'] = source_url

        # ISequence represents an orderable collection
        if ISequence.providedBy(self.field) or self.orderable:
            args['pattern_options']['orderable'] = True

        if self.vocabulary == 'plone.app.vocabularies.Keywords':
            membership = getToolByName(context, 'portal_membership')
            user = membership.getAuthenticatedMember()

            registry = getUtility(IRegistry)
            roles_allowed_to_add_keywords = registry.get(
                'plone.roles_allowed_to_add_keywords', [])
            roles = set(user.getRolesInContext(context))

            allowNewItems = 'false'
            if roles.intersection(roles_allowed_to_add_keywords):
                allowNewItems = 'true'
            args['pattern_options']['allowNewItems'] = allowNewItems

        return args
Пример #21
0
 def testImplements(self):
     field = Tuple()
     self.failUnless(ITuple.providedBy(field))
     self.failUnless(ISequence.providedBy(field))
     self.failUnless(ICollection.providedBy(field))
Пример #22
0
def decode(data, schema, missing=True, primary=False):
    """Decode a data dict according to a schema. The returned dictionary will
    contain only keys matching schema names, and will force type values
    appropriately.

    This function is only necessary because the encoders used by encode()
    are not sufficiently detailed to always return the exact type expected
    by a field, e.g. resulting in ascii/unicode discrepancies.

    If missing is True, fields that are in the schema but not in the data will
    be set to field.missing_value. Otherwise, they are ignored.

    If primary is True, also fields that are marged as primary fields are
    decoded from the data. (Primary fields are not decoded by default,
    because primary field are mainly used for rich text or binary fields
    and data is usually parsed from query string with length limitations.)
    """

    decoded = {}

    for name, field in getFields(schema).items():
        if not primary and HAS_RFC822 and IPrimaryField.providedBy(field):
            continue

        if name not in data:
            if missing:
                decoded[name] = field.missing_value
            continue

        value = data[name]
        if value is None:
            continue

        field_type = field._type
        if isinstance(field_type, (tuple, list,)):
            field_type = field_type[-1]

        if ISequence.providedBy(field):
            converted = []

            value_type_field_type = field.value_type._type
            if isinstance(value_type_field_type, (tuple, list,)):
                value_type_field_type = value_type_field_type[-1]

            for item in value:
                if field.value_type._type and not isinstance(
                        item, field.value_type._type):
                    item = value_type_field_type(item)
                converted.append(item)

            value = converted
        elif isinstance(value, (tuple, list)) and value:
            value = value[0]

        if isinstance(value, six.binary_type):
            value = value.decode('utf-8')

        if field._type is not None and not isinstance(value, field._type):
            value = field_type(value)

        decoded[name] = value

    return decoded
Пример #23
0
    def _base_args(self):
        """Method which will calculate _base class arguments.

        Returns (as python dictionary):
            - `pattern`: pattern name
            - `pattern_options`: pattern options
            - `name`: field name
            - `value`: field value

        :returns: Arguments which will be passed to _base
        :rtype: dict
        """

        args = super(AjaxSelectWidget, self)._base_args()

        args['name'] = self.name
        args['value'] = self.value

        args.setdefault('pattern_options', {})

        field_name = self.field and self.field.__name__ or None

        context = self.context
        view_context = get_widget_form(self)
        # For EditForms and non-Forms (in tests), the vocabulary is looked
        # up on the context, otherwise on the view
        if (
            IEditForm.providedBy(view_context) or
            not IForm.providedBy(view_context)
        ):
            view_context = context

        vocabulary_name = self.vocabulary
        field = None
        if IChoice.providedBy(self.field):
            args['pattern_options']['maximumSelectionSize'] = 1
            field = self.field
        elif ICollection.providedBy(self.field):
            field = self.field.value_type
        if IChoice.providedBy(field):
            args['pattern_options']['allowNewItems'] = 'false'

        args['pattern_options'] = dict_merge(
            get_ajaxselect_options(view_context, args['value'], self.separator,
                                   vocabulary_name, self.vocabulary_view,
                                   field_name),
            args['pattern_options'])

        if field and getattr(field, 'vocabulary', None):
            form_url = self.request.getURL()
            source_url = '{0:s}/++widget++{1:s}/@@getSource'.format(
                form_url,
                self.name
            )
            args['pattern_options']['vocabularyUrl'] = source_url

        # ISequence represents an orderable collection
        if ISequence.providedBy(self.field) or self.orderable:
            args['pattern_options']['orderable'] = True

        if self.vocabulary == 'plone.app.vocabularies.Keywords':
            membership = getToolByName(context, 'portal_membership')
            user = membership.getAuthenticatedMember()

            registry = getUtility(IRegistry)
            roles_allowed_to_add_keywords = registry.get(
                'plone.roles_allowed_to_add_keywords', [])
            roles = set(user.getRolesInContext(context))

            allowNewItems = 'false'
            if roles.intersection(roles_allowed_to_add_keywords):
                allowNewItems = 'true'
            args['pattern_options']['allowNewItems'] = allowNewItems

        return args