def get_data(self):
        """Return an iterable of HTML snippets representing the files already
        stored on the context and allowing to download it.
        If the widget is in input mode then removal is allowed too.
        """
        if self.value:
            # Depending on when this gets called we'll have INamedFile's,
            # strings ("index:N") or FileUpload's (on failed validations).
            # We have to filter out the FileUpload's since the uploads are gone
            # and we can do nothing about it.
            sub_values = [
                i for i in self.value
                if INamedFile.providedBy(i) or isinstance(i, basestring)
            ]

            converter = IDataConverter(self)
            converted_value = converter.toFieldValue(sub_values)

            if self.form is not None:
                view_name = self.name[len(self.form.prefix):]
                view_name = view_name[len(self.form.widgets.prefix):]
            else:
                view_name = ''

            for i, value in enumerate(converted_value):
                form_value = 'index:%s' % i
                download_url = '%s/++widget++%s/%i/@@download/%s' % (
                    self.request.getURL(),
                    view_name,
                    i,
                    value.filename,
                )

                yield self.render_file(form_value, value, download_url)
Example #2
0
    def extract(self, default=NO_VALUE):
        value = self.request.get(self.name, default)
        converter = IDataConverter(self)
        try:
            c_value = converter.toFieldValue(value)
        except:
            return value

        unit_name = self.request.get(self.name + '-unit')
        if unit_name and unit_name != self.base_unit:
            try:
                unit = getattr(ureg, unit_name)
                base_unit = getattr(ureg, self.base_unit)
            except UndefinedUnitError:
                c_value = self.field.get(self.context)

            # Do the conversion
            try:
                c_value = c_value * unit
            except TypeError:
                return value
            else:
                c_value = c_value.to(base_unit).magnitude
            if not self.ignoreContext:
                self._set_unit_annotation(unit_name)
            value = converter.toWidgetValue(c_value)

        return value
Example #3
0
    def update(self):
        """\
        Customized update method.
        """

        # Since we are interested in acquring what the context had first
        # before we are interested in what was submitted in the request,
        # we forcibly set ignoreRequest on and continue as normal.  Once
        # that is done, process the request as normal.

        ignoreRequest = self.ignoreRequest
        self.ignoreRequest = True
        super(StorageFileSelectWidget, self).update()
        # Restore original value.
        self.ignoreRequest = ignoreRequest

        if not ignoreRequest:
            # Extract the request value like how the parent would have 
            # done
            widget_value = self.extract()

            if widget_value not in (NO_VALUE, INVALID_VALUE):
                # Only set the widget with the value from request that
                # is valid
                self.value = widget_value
                # As this deferred self.value assignment from request
                # is complete, with everything else done, return here.
                return

        # The follow are steps that should also have been done inside
        # step 1.2 in that method.  To begin validate that the
        # applicable conditions are available.
        if not IFieldWidget.providedBy(self):
            return

        # Always set errors, since context could provide an invalid
        # value due to changing conditions.
        self.setErrors = True

        # Now verify that the current widget value (which is extracted
        # by the data manager) is valid, attempt the conversion back to
        # the field value using toFieldValue as the reverse method
        # toWidgetValue does not and cannot raise exceptions due to
        # how and where it is used by the parent update method.

        converter = IDataConverter(self)
        try:
            converter.toFieldValue(self.value)
        except (zope.interface.Invalid, ValueError), error:
            # We have an exception, so we adapt and set the error view.
            view = zope.component.getMultiAdapter(
                (error, self.request, self, self.field,
                 self.form, self.context), IErrorViewSnippet)
            view.update()
            self.error = view
Example #4
0
 def getValue(self, language):
     self.value = removeSecurityProxy(self.value)
     if not isinstance(self.value, dict) and \
        not isinstance(self.value, PersistentDict):
         converter = IDataConverter(self)
         try:
             self.value = converter.toFieldValue(self.value)
         except Exception:
             self.value = {}
     if self.value is not None:
         return self.value.get(language)
 def getValue(self, language):
     self.value = removeSecurityProxy(self.value)
     if not isinstance(self.value, dict) and \
        not isinstance(self.value, PersistentDict):
         converter = IDataConverter(self)
         try:
             self.value = converter.toFieldValue(self.value)
         except Exception:
             self.value = {}
     if self.value is not None:
         return self.value.get(language)
def populate_dexterity(obj, data):
    request = getRequest()
    for schema in get_dexterity_schemas(context=obj):
        for name in getFieldNames(schema):
            field = schema[name]
            if name in ['expires', 'effective', 'relatedItems']:
                # skip some fields
                continue
            if getattr(field, 'readonly', False):
                continue
            autoform_widgets = schema.queryTaggedValue(WIDGETS_KEY, default={})
            if name in autoform_widgets:
                try:
                    widgetclass = utils.resolveDottedName(
                        autoform_widgets[name])
                except AttributeError:
                    # XXX: Investigate:
                    # AttributeError: 'ParameterizedWidget' object has no
                    # attribute 'split'
                    continue
                widget = widgetclass(field, request)
            else:
                widget = component.getMultiAdapter(
                    (field, request), IFieldWidget)

            widget.context = obj
            widget.ignoreRequest = True
            widget.update()

            if HAS_RECURRENCE_WIDGET and IRecurrenceWidget.providedBy(widget):
                # We cannot yet deal with the recurrence widget
                continue

            if name == 'title':
                value = unicode(data['title'])
            else:
                value = widget.value
                if not value or value in [NOT_CHANGED, NO_VALUE] or \
                        not IDataConverter(widget).toFieldValue(value):
                    value = get_dummy_dexterity_value(obj, widget, data)
                    if value is None:
                        continue
                    if interfaces.ICollection.providedBy(widget.field) or \
                            interfaces.IChoice.providedBy(widget.field):
                        value = [value]

            if value:
                dm = component.getMultiAdapter((obj, field), IDataManager)
                try:
                    dm.set(IDataConverter(widget).toFieldValue(value))
                except TypeError:
                    dm.set(value)
    def _setAsOwner(self, context, field, value):
        # Do some trivial transforms
        def transform(value, field):
            if isinstance(field, Set) and isinstance(value, unicode):
                value = set((value, ))
            elif isinstance(field, Set) and isinstance(value, tuple):
                value = set(value)
            elif isinstance(field, Set) and isinstance(value, list):
                value = set(value)
            elif isinstance(field, List) and isinstance(value, unicode):
                value = list((value, ))
            elif (isinstance(field, Choice) and isinstance(value, list)
                  and len(value) == 1):
                value = value[0]
            return value

        # Try to set the value on created object
        value = transform(value, field)
        try:
            # 2) Try your luck with z3c.form adapters
            widget = getMultiAdapter((field, getRequest()), IFieldWidget)
            converter = IDataConverter(widget)
            dm = getMultiAdapter((context, field), IDataManager)

            # Convert datetimes to collective.z3cform.datetimewidget-compatible
            if isinstance(field, Datetime) and isinstance(
                    widget, DatetimeWidget):  # noqa
                value = re.compile('\d+').findall(value)

            # Convert dates to collective.z3cform.datetimewidget-compatible
            if isinstance(field, Date) and isinstance(widget, DateWidget):
                value = re.compile('\d+').findall(value[:10])  # YYYY-MM-DD
            # Convert dates to plone.app.z3cform.widgets.datewidget-compatible
            elif isinstance(field, Date):
                value = value.split()[0]

            dm.set(converter.toFieldValue(value))
        except ConflictError:
            raise
        except Exception, e:
            try:
                # 1) Try to set it directly
                bound_field = field.bind(context)
                bound_field.validate(value)
                bound_field.set(context, value)
            except ConflictError:
                raise
            except Exception:
                LOG.error(e)
                return u'An unexpected error: {0:s} {1:s}'.format(
                    e.__class__, e)
    def _setAsOwner(self, context, field, value):
        # Do some trivial transforms
        def transform(value, field):
            if isinstance(field, Set) and isinstance(value, unicode):
                value = set((value,))
            elif isinstance(field, Set) and isinstance(value, tuple):
                value = set(value)
            elif isinstance(field, Set) and isinstance(value, list):
                value = set(value)
            elif isinstance(field, List) and isinstance(value, unicode):
                value = list((value,))
            elif (isinstance(field, Choice) and
                  isinstance(value, list) and len(value) == 1):
                value = value[0]
            return value

        # Try to set the value on created object
        value = transform(value, field)
        try:
            # 2) Try your luck with z3c.form adapters
            widget = getMultiAdapter((field, getRequest()), IFieldWidget)
            converter = IDataConverter(widget)
            dm = getMultiAdapter((context, field), IDataManager)

            # Convert datetimes to collective.z3cform.datetimewidget-compatible
            if isinstance(field, Datetime) and isinstance(widget, DatetimeWidget):  # noqa
                value = re.compile('\d+').findall(value)

            # Convert dates to collective.z3cform.datetimewidget-compatible
            if isinstance(field, Date) and isinstance(widget, DateWidget):
                value = re.compile('\d+').findall(value[:10])  # YYYY-MM-DD
            # Convert dates to plone.app.z3cform.widgets.datewidget-compatible
            elif isinstance(field, Date):
                value = value.split()[0]

            dm.set(converter.toFieldValue(value))
        except ConflictError:
            raise
        except Exception, e:
            try:
                # 1) Try to set it directly
                bound_field = field.bind(context)
                bound_field.validate(value)
                bound_field.set(context, value)
            except ConflictError:
                raise
            except Exception:
                LOG.error(e)
                return u'An unexpected error: {0:s} {1:s}'.format(
                    e.__class__, e)
    def inject_default_values(self):
        today = date.today()
        title = self.widgets['title']
        date_from = self.widgets['date_from']
        date_to = self.widgets['date_to']

        if not title.value:
            title.value = unicode(today.year)
        if not date_from.value:
            date_from.value = IDataConverter(date_from).toWidgetValue(
                date(today.year, 1, 1))
        if not date_to.value:
            date_to.value = IDataConverter(date_to).toWidgetValue(
                date(today.year, 12, 31))
Example #10
0
 def _init_baseform(self):
     """
     Initialize base form for re-use * N rows to avoid re-construction;
     should be called by self.update(), just once.
     """
     row_views = {
         ('edit', 'Stacked'): DivRowForm,
         ('view', 'Stacked'): DivRowDisplayForm,
         ('edit', 'Columns'): RowForm,
         ('view', 'Columns'): RowDisplayForm,
     }
     row_view_cls = row_views[(self.VIEWNAME, self.displaymode)]
     self.dummy_record = self.context.create()
     alsoProvides(self.dummy_record, self.schema)
     self.baseform = row_view_cls(self.dummy_record, self.schema,
                                  self.request)
     self.baseform.update()
     # create a mapping of data converters by fieldname
     self.converters = {}  # fieldname to converter
     self.defaults = {}  # fieldname to default value
     for fieldname in self.baseform.fields:
         widget = self.baseform.widgets[fieldname]
         field = self.schema[fieldname]
         self.converters[fieldname] = IDataConverter(widget)
         self.defaults[fieldname] = field.default
         # lookup template once, bind -- to avoid repeated lookup
         widget.template = getMultiAdapter(
             (widget.context, self.request, self.baseform, field, widget),
             IPageTemplate,
             name=widget.mode)
     self.baseform.render()  # force chameleon compilation here
Example #11
0
    def widgets(self, mode=DISPLAY_MODE):
        """Return the widgets for the databox

        # https://stackoverflow.com/questions/8476781/how-to-access-z3c-form-widget-settings-from-browser-view
        """
        widgets = []
        fields = api.get_fields(self.context)
        for name, field in fields.items():
            widget = getMultiAdapter((field, self.request), IFieldWidget)
            widget.mode = mode
            widget.context = self.context
            converter = IDataConverter(widget)
            value = field.get(self.context)
            widget.value = converter.toWidgetValue(value)
            widget.update()
            widgets.append(widget)
        return widgets
Example #12
0
    def replace_term(self, schema, field, fkey, match):
        """
        Replace a field term. For multi valued fields it will replace just the matching part of it. For single
        valued fields it replaces the whole field, where it matches. We get the widget from the actual schema field
        so we can use it to extract and parse the appropriate value too (!)

        :param schema: dotted name schema (str)
        :param field: field
        :param fkey: boolean, representing DateGridField
        :param match: the value being matched
        :return: None
        """
        widget = self.replacement_widget
        replacement = widget.extract()
        if replacement is not NO_VALUE:
            try:
                replacement = IDataConverter(widget).toFieldValue(replacement)
            except WrongType:
                # for some reason some things that should come in as unicode are coming in as strings
                replacement = IDataConverter(widget).toFieldValue(IDataConverter(widget).toWidgetValue(replacement))
        if not replacement or replacement is NO_VALUE:
            api.portal.show_message(message=_('No replacement value given'), request=self.request, type='error')
            return

        results = self.results()
        for brain in results:
            obj = brain.getObject()
            field_value = getattr(obj, field, None)

            if isinstance(field_value, str) or \
                    isinstance(field_value, datetime.date) or isinstance(field_value, datetime.datetime):
                self.set_value(obj, schema, field, replacement)
            elif isinstance(field_value, tuple) or isinstance(field_value, list):
                if fkey:
                    for item_value in field_value:
                        if item_value[fkey] == match:
                            item_value[fkey] = replacement
                    self.set_value(obj, schema, field, field_value)
                else:
                    if replacement in field_value:
                        field_value = [item_value for item_value in field_value if item_value != match]
                    else:
                        field_value = [item_value == match and replacement or item_value for item_value in field_value]
                    self.set_value(obj, schema, field, field_value)
        api.portal.show_message(message=_('Replaced term in {} records'.format(len(results))),
                                request=self.request, type='info')
Example #13
0
    def updateWidgets(self, *args, **kwargs):
        super(AddWebactionForm, self).updateWidgets(*args, **kwargs)

        saving = 'form.buttons.save' in self.request
        # Prefill other widgets only upon initial rendering of the form,
        # not when trying to save - this is so we don't override
        # actual user provided inputs with missing values
        if saving:
            return

        # Prefill form widgets with missing values
        for widget in self.widgets.values():
            missing_value = widget.field.missing_value
            if not missing_value:
                continue
            converter = IDataConverter(widget)
            widget.value = converter.toWidgetValue(missing_value)
Example #14
0
    def updateWidgets(self, *args, **kwargs):
        super(AddWebactionForm, self).updateWidgets(*args, **kwargs)

        saving = 'form.buttons.save' in self.request
        # Prefill other widgets only upon initial rendering of the form,
        # not when trying to save - this is so we don't override
        # actual user provided inputs with missing values
        if saving:
            return

        # Prefill form widgets with missing values
        for widget in self.widgets.values():
            missing_value = widget.field.missing_value
            if not missing_value:
                continue
            converter = IDataConverter(widget)
            widget.value = converter.toWidgetValue(missing_value)
    def get_data(self):
        """
        """
        if self.value:
            # sometimes the value contains the strings from the form,
            # sometimes it's already converted by the converter. But
            # if we have errors and we are trying to add a new file
            # (thats when entry is a unicode string) we need to put
            # that string again in the form since we did not store the
            # file yet, but we can get the file from the converter..
            converter = IDataConverter(self)
            converted_value = converter.toFieldValue(self.value)
            for i, key_or_file in enumerate(self.value):
                if isinstance(key_or_file, unicode):
                    file_ = converted_value[i]
                    yield self.render_file(file_, value=key_or_file)

                else:
                    yield self.render_file(key_or_file, index=i)
    def inject_initial_data(self):
        if self.request.method != 'GET':
            return

        values = self.model.get_edit_values(self.fields.keys())

        for fieldname, value in values.items():
            widget = self.widgets[fieldname]
            value = IDataConverter(widget).toWidgetValue(value)
            widget.value = value
Example #17
0
    def updateWidgets(self, *args, **kwargs):
        super(EditKeyForm, self).updateWidgets(*args, **kwargs)

        saving = 'form.buttons.save' in self.request

        # Prefill form widgets with persisted values from DB
        key = self.get_key()
        for widget in self.widgets.values():
            # Always prefill readonly widgets.
            #
            # Prefill other widgets only upon initial rendering of the form,
            # not when trying to save - this is so we don't override
            # actual user provided inputs with persisted values from the
            # DB when rendering the form in the case of validation errors.
            if widget.field.readonly or not saving:
                name = widget.field.getName()
                value = key[name]
                converter = IDataConverter(widget)
                widget.value = converter.toWidgetValue(value)
Example #18
0
    def updateWidgets(self):
        super(ParticipationEditForm, self).updateWidgets()

        if self.request.method != 'GET':
            return

        widget = self.widgets['roles']
        widget.value = IDataConverter(widget).toWidgetValue(
            [role.role for role in self.model.roles])

        self.widgets.update()
Example #19
0
            def update(self):
                """Update the widget-values of the dossier add-form
                with the values of the selected dossiertemplate values.
                """
                super(WrappedForm, self).update()

                if not getSecurityManager().getUser().getId():
                    # this happens during ++widget++ traversal
                    return

                self.is_available()

                template_obj = get_saved_template_obj(self.context)

                if not template_obj:
                    # This happens if the user access the step directly and
                    # the wizard storage was expired or never existent.
                    return self.request.RESPONSE.redirect(
                        '{}/dossier_with_template'.format(
                            self.context.absolute_url()))

                template_values = template_obj.get_schema_values()
                title_help = IDossierTemplateSchema(template_obj).title_help

                for group in self.groups:
                    for widgetname in group.widgets:

                        # Skip not whitelisted template fields.
                        # We don't want to update fields which are not
                        # whitelisted in the template.
                        template_widget_name = self.get_template_widget_name(
                            widgetname)
                        if template_widget_name not in TEMPLATABLE_FIELDS:
                            continue

                        value = template_values.get(template_widget_name)
                        widget = group.widgets.get(widgetname)

                        # If the current field is the title field and the
                        # title_help is set, we remove the input-value and
                        # add a field description with the title_help text
                        # instead.
                        if widget.field == IOpenGeverBase[
                                'title'] and title_help:
                            widget.dynamic_description = title_help
                            value = ''

                        # Set the template value to the dossier add-form widget.
                        widget.value = IDataConverter(widget).toWidgetValue(
                            value)

                        if widgetname == 'IDossier.keywords':
                            self._modify_keyword_widget_according_to_template(
                                widget)
Example #20
0
    def widget_value(self):
        """Return the converted value."""
        self.unit = self.request.get(self.name + '-unit', self.preferred_unit)
        if not self.value:
            return

        try:
            base_unit = getattr(ureg, self.base_unit)
        except UndefinedUnitError:
            value = self.value
        else:
            # Do the conversion
            converter = IDataConverter(self)
            try:
                value = converter.toFieldValue(self.value)
            except:
                return self.value
            system = None
            if not self.ignoreContext:
                system = self._get_unit_annotation()
            else:
                if self.unit in interfaces.METRICS:
                    system = interfaces.SYSTEM_METRIC
                elif self.unit in interfaces.IMPERIALS:
                    system = interfaces.SYSTEM_IMPERIAL
            if not system in self.unit_systems:
                system = self.preferred_system
            self.unit = utils.get_best_unit(
                value,
                system,
                self.unit_dimension,
                level_min=self.level_min,
                level_max=self.level_max,
            )[0]
            unit = getattr(ureg, self.unit)
            value = value * base_unit
            value = value.to(unit).magnitude
            if isinstance(value, Decimal):
                value = value.quantize(interfaces.TWOPLACES)
            value = converter.toWidgetValue(value)
        return value
 def _setAsOwner(self, context, field, value):
     # Try to set the value on creted object
     try:
         # 1) Try to set it directly
         bound_field = field.bind(context)
         bound_field.validate(value)
         bound_field.set(context, value)
     except ConflictError:
         raise
     except Exception, e:
         try:
             # 2) Try your luck with z3c.form adapters
             widget = getMultiAdapter((field, getRequest()), IFieldWidget)
             converter = IDataConverter(widget)
             dm = getMultiAdapter((context, field), IDataManager)
             dm.set(converter.toFieldValue(value))
         except ConflictError:
             raise
         except Exception:
             LOG.error(e)
             return u"An unexpected error: %s" % e
Example #22
0
    def updateWidgets(self, *args, **kwargs):
        super(EditWebactionForm, self).updateWidgets(*args, **kwargs)

        saving = 'form.buttons.save' in self.request

        # Prefill form widgets with persisted values from DB or
        # with missing value if needed
        webaction = self.get_webaction()
        for widget in self.widgets.values():
            # Always prefill readonly widgets.
            #
            # Prefill other widgets only upon initial rendering of the form,
            # not when trying to save - this is so we don't override
            # actual user provided inputs with persisted values from the
            # DB when rendering the form in the case of validation errors.
            if widget.field.readonly or not saving:
                name = widget.field.getName()
                value = webaction.get(name, widget.field.missing_value)
                if value is None:
                    continue
                converter = IDataConverter(widget)
                widget.value = converter.toWidgetValue(value)
    def _setAsOwner(self, context, field, value):
        # Do some trivial transforms
        def transform(value, field):
            if isinstance(field, Set) and isinstance(value, unicode):
                value = set((value,))
            elif isinstance(field, Set) and isinstance(value, tuple):
                value = set(value)
            elif isinstance(field, Set) and isinstance(value, list):
                value = set(value)
            elif isinstance(field, List) and isinstance(value, unicode):
                value = list((value,))
            elif (isinstance(field, Choice)
                  and isinstance(value, list) and len(value) == 1):
                value = value[0]
            return value

        # Try to set the value on created object
        value = transform(value, field)
        try:
            # 1) Try to set it directly
            bound_field = field.bind(context)
            bound_field.validate(value)
            bound_field.set(context, value)
        except ConflictError:
            raise
        except Exception, e:
            try:
                # 2) Try your luck with z3c.form adapters
                widget = getMultiAdapter((field, getRequest()), IFieldWidget)
                converter = IDataConverter(widget)
                dm = getMultiAdapter((context, field), IDataManager)
                dm.set(converter.toFieldValue(value))
            except ConflictError:
                raise
            except Exception:
                LOG.error(e)
                return u"An unexpected error: %s %s" % (e.__class__, e)
    def inject_initial_data(self):
        if self.request.method != 'GET':
            return

        values = self.model.get_edit_values(self.fields.keys())
        # XXX - Doing this instead of a data adapter
        secretary = values.get('secretary')
        if secretary:
            if isinstance(secretary, User):
                values['secretary'] = secretary.userid

        for fieldname, value in values.items():
            widget = self.widgets[fieldname]
            value = IDataConverter(widget).toWidgetValue(value)
            widget.value = value
Example #25
0
    def extract(self, default=NOVALUE):  # noqa
        action = self.request.get('{0}.action'.format(self.name), None)
        if self.request.get('PATH_INFO',
                            '').endswith('kss_z3cform_inline_validation'):
            action = 'nochange'

        if action == 'remove':
            return None
        elif action == 'nochange':
            session = ISession(self.request)[SESSION_PKG_KEY]
            token = self.uploaded_token
            if token is None:
                token = self.request.get('{0}.token'.format(self.name), None)
            if token in session:
                self.uploaded_token = token
                return session.get(token)
            if self.value is not None:
                return self.value
            if self.ignoreContext:
                return default
            dm = getMultiAdapter((self.context, self.field), IDataManager)
            value = dm.query()

            if isinstance(value, Proxy):
                value = removeSecurityProxy(value)
            return value
        elif action == 'replace':
            # set the action back to 'nochange' so that the button is
            # preselected. Only applicable when form is reloaded with errors
            self.request.form['{0}.action'.format(self.name)] = 'nochange'

        # empty unnamed FileUploads should not count as a value
        value = super(NamedFileWidget, self).extract(default)
        if isinstance(value, FileUpload):
            value.seek(0, SEEK_END)
            empty = value.tell() == 0
            value.seek(0)
            if empty and not value.filename:
                return default
            value.seek(0)
            session = ISession(self.request)[SESSION_PKG_KEY]
            if self.unique_token not in session:
                self.uploaded_token = self.unique_token
                value = IDataConverter(self).toFieldValue(value)
                session[self.unique_token] = value
        elif not value:
            return default
        return value
Example #26
0
    def jsonValidate(self, id, value):
        """Validate the value for the witdget with the given DOM field id."""
        res = u'OK'
        data = {}
        errorView = None
        self.context.updateWidgets()
        widget = util.getWidgetById(self.context, id)
        if widget is not None: 
            content = self.context.widgets.content
            form = self.context.widgets.form
            try:
                value = IDataConverter(widget).toFieldValue(value)
                validator = zope.component.getMultiAdapter((content, self.request, 
                    self.context, getattr(widget, 'field', None), widget), IValidator)
                error = validator.validate(value)

            except (zope.schema.ValidationError, ValueError), error:
                errorView = zope.component.getMultiAdapter(
                    (error, self.request, widget, widget.field,
                     form, content), IErrorViewSnippet)
                errorView.update()
    def test_widgets_render_missing_values(self):
        """Test that gets run for each of the portal type specific subclasses,
        and asserts that a rendered z3c.form widget correctly returns the
        missing value if that's what's currently persisted on the object.
        """
        if self.portal_type is None:
            # Don't attempt to run this test for the abstract base class
            return

        self.login(self.manager)

        obj = self.get_obj_of_own_type()
        form = DefaultEditForm(obj, self.request)

        # Populate the form with fields according to the object's portal type
        with fake_interaction():
            # We need a fake IInteraction context because otherwise
            # z3c.formwidget.query.widget fails with its checkPermission()
            form.update()

        for widget in self.iter_widgets(form):
            field = widget.field

            if field.required:
                # Required fields shouldn't have missing values
                return

            if field.readonly:
                return

            # Determine what this field's missing value would be
            missing_value = field.missing_value

            # Manipulate fixture obj to have missing value for this field
            field.set(field.interface(obj), missing_value)

            # Update the widget to reflect that changed value on the obj
            with fake_interaction():
                widget.update()

            # Use the widget to retrieve the value - but turn it into a
            # field value using the field's DataConverter, in order to
            # compare it to missing value.
            dc = IDataConverter(widget)
            field_value_from_widget = dc.toFieldValue(widget.value)

            if isinstance(widget, SingleCheckBoxWidget):
                # Boolean fields handled by SingleCheckBoxWidgets are funny:
                # Their fields' missing value is None, which ends up
                # as a widget.value of empty list [], which
                # IDataConverter.toFieldValue() then turns into False.
                #
                # In other words, there isn't really a concept of missing
                # values for booleans - MV will always end up being
                # considered the same as False.
                if field_value_from_widget is False:
                    field_value_from_widget = None

            if isinstance(field, List) and isinstance(widget, CheckBoxWidget):
                # zope.schema.List is weird too - it gets rendered using
                # a CheckBoxWidget.
                missing_value = []

            self.assertEqual(
                missing_value, field_value_from_widget,
                'Unexpectedly got %r instead of missing value %r '
                'from widget %r (for an %r object) ' % (
                    field_value_from_widget, missing_value,
                    widget, obj.portal_type))
Example #28
0
    def create_content(self, *args, **kwargs):
        """Create content and return its UID"""
        disableCSRFProtection()
        # XXX: Because kwargs are only supported with robotframework >= 2.8.3,
        # we must parse them here to support robotframework < 2.8.3.
        for arg in [x for x in args if '=' in x]:
            name, value = arg.split('=', 1)
            kwargs[name] = value

        assert 'type' in kwargs, u"Keyword arguments must include 'type'."
        portal_type = kwargs.get('type')
        portal = getSite()
        if 'container' in kwargs:
            pc = getToolByName(portal, 'portal_catalog')
            uid_or_path = kwargs.pop('container')
            uid_results =\
                pc.unrestrictedSearchResults(UID=uid_or_path)
            path_results = \
                pc.unrestrictedSearchResults(
                    path={'query': uid_or_path.rstrip('/'), 'depth': 0})
            container =\
                (uid_results or path_results)[0]._unrestrictedGetObject()
        else:
            container = portal

        # if we create 'file' and 'image' kwargs entries, they should not be
        # used to create the content but be set afterwards
        create_kwargs = {}
        create_kwargs.update(kwargs)

        if HAS_DEXTERITY:
            if portal_type in ('File', ) and 'file' not in kwargs:
                pdf_file = os.path.join(os.path.dirname(__file__), 'content',
                                        u'file.pdf')
                value = NamedBlobFile(data=open(pdf_file, 'r').read(),
                                      contentType='application/pdf',
                                      filename=u'file.pdf')
                kwargs['file'] = value

        if portal_type in ('Image', 'News Item') and 'image' not in kwargs:
            prefill_image_types(portal, kwargs)

        id_ = kwargs.pop('id', None)
        type_ = kwargs.pop('type')

        content = None
        if HAS_DEXTERITY:
            # The title attribute for Dexterity types needs to be unicode
            if 'title' in kwargs and isinstance(kwargs['title'], str):
                kwargs['title'] = kwargs['title'].decode('utf-8')
            from plone.dexterity.interfaces import IDexterityFTI
            from plone.dexterity.utils import createContentInContainer
            try:
                getUtility(IDexterityFTI, name=type_)
                content = createContentInContainer(container, type_,
                                                   **create_kwargs)
                if id_ is not None and content.id != id_:
                    container.manage_renameObject(content.id, id_)
            except ComponentLookupError:
                pass

        if HAS_DEXTERITY and content:
            # For dexterity-types, we need a second pass to fill all fields
            # using their widgets to get e.g. RichText-values created
            # correctly.
            fti = getUtility(IDexterityFTI, name=type_)
            schema = fti.lookupSchema()
            fields = {}
            for name in schema:
                fields[name] = schema[name]
            for schema in getAdditionalSchemata(portal_type=type_):
                for name in schema:
                    fields[name] = schema[name]
            for name, field in fields.items():
                widget = queryMultiAdapter((field, getRequest()), IFieldWidget)
                if widget and name in kwargs:
                    if not IFromUnicode.providedBy(field):
                        value = kwargs[name]
                    elif isinstance(kwargs[name], unicode):
                        value = kwargs[name]
                    else:
                        value = unicode(str(kwargs[name]),
                                        'utf-8',
                                        errors='ignore')
                    converter = IDataConverter(widget)
                    dm = queryMultiAdapter((content, field), IDataManager)
                    if dm:
                        dm.set(converter.toFieldValue(value))

        if content is None:
            if id_ is None:
                normalizer = queryUtility(IURLNormalizer)
                id_ = normalizer.normalize(kwargs['title'])

            # It must be Archetypes based content:
            content = container[container.invokeFactory(type_, id_, **kwargs)]
            content.processForm()

        return IUUID(content)
    def create_content(self, *args, **kwargs):
        """Create content and return its UID"""
        disableCSRFProtection()
        # XXX: Because kwargs are only supported with robotframework >= 2.8.3,
        # we must parse them here to support robotframework < 2.8.3.
        for arg in [x for x in args if '=' in x]:
            name, value = arg.split('=', 1)
            kwargs[name] = value

        assert 'type' in kwargs, u"Keyword arguments must include 'type'."
        portal_type = kwargs.get('type')
        portal = getSite()
        if 'container' in kwargs:
            pc = getToolByName(portal, 'portal_catalog')
            uid_or_path = kwargs.pop('container')
            uid_results =\
                pc.unrestrictedSearchResults(UID=uid_or_path)
            path_results = \
                pc.unrestrictedSearchResults(
                    path={'query': uid_or_path.rstrip('/'), 'depth': 0})
            container =\
                (uid_results or path_results)[0]._unrestrictedGetObject()
        else:
            container = portal

        # if we create 'file' and 'image' kwargs entries, they should not be
        # used to create the content but be set afterwards
        create_kwargs = {}
        create_kwargs.update(kwargs)

        if HAS_DEXTERITY:
            if portal_type in ('File', ) and 'file' not in kwargs:
                pdf_file = os.path.join(
                    os.path.dirname(__file__), 'content', u'file.pdf')
                value = NamedBlobFile(
                    data=open(pdf_file, 'r').read(),
                    contentType='application/pdf',
                    filename=u'file.pdf'
                )
                kwargs['file'] = value

        if portal_type in ('Image', 'News Item') and 'image' not in kwargs:
            prefill_image_types(portal, kwargs)

        id_ = kwargs.pop('id', None)
        type_ = kwargs.pop('type')

        content = None
        if HAS_DEXTERITY:
            # The title attribute for Dexterity types needs to be unicode
            if 'title' in kwargs and isinstance(kwargs['title'], str):
                kwargs['title'] = kwargs['title'].decode('utf-8')
            from plone.dexterity.interfaces import IDexterityFTI
            from plone.dexterity.utils import createContentInContainer
            try:
                getUtility(IDexterityFTI, name=type_)
                content = createContentInContainer(
                    container, type_, **create_kwargs)
                if id_ is not None and content.id != id_:
                    container.manage_renameObject(content.id, id_)
            except ComponentLookupError:
                pass

        if HAS_DEXTERITY and content:
            # For dexterity-types, we need a second pass to fill all fields
            # using their widgets to get e.g. RichText-values created
            # correctly.
            fti = getUtility(IDexterityFTI, name=type_)
            schema = fti.lookupSchema()
            fields = {}
            for name in schema:
                fields[name] = schema[name]
            for schema in getAdditionalSchemata(portal_type=type_):
                for name in schema:
                    fields[name] = schema[name]
            for name, field in fields.items():
                widget = queryMultiAdapter((field, getRequest()), IFieldWidget)
                if widget and name in kwargs:
                    if not IFromUnicode.providedBy(field):
                        value = kwargs[name]
                    elif isinstance(kwargs[name], unicode):
                        value = kwargs[name]
                    else:
                        value = unicode(str(kwargs[name]), 'utf-8',
                                        errors='ignore')
                    converter = IDataConverter(widget)
                    dm = queryMultiAdapter((content, field), IDataManager)
                    if dm:
                        dm.set(converter.toFieldValue(value))

        if content is None:
            if id_ is None:
                normalizer = queryUtility(IURLNormalizer)
                id_ = normalizer.normalize(kwargs['title'])

            # It must be Archetypes based content:
            content = container[container.invokeFactory(type_, id_, **kwargs)]
            content.processForm()

        return IUUID(content)
    def test_widgets_render_missing_values(self):
        """Test that gets run for each of the portal type specific subclasses,
        and asserts that a rendered z3c.form widget correctly returns the
        missing value if that's what's currently persisted on the object.
        """
        if self.portal_type is None:
            # Don't attempt to run this test for the abstract base class
            return

        self.login(self.manager)

        obj = self.get_obj_of_own_type()
        form = DefaultEditForm(obj, self.request)

        # Populate the form with fields according to the object's portal type
        with fake_interaction():
            # We need a fake IInteraction context because otherwise
            # z3c.formwidget.query.widget fails with its checkPermission()
            form.update()

        for widget in self.iter_widgets(form):
            field = widget.field

            if field.required:
                # Required fields shouldn't have missing values
                return

            if field.readonly:
                return

            # Determine what this field's missing value would be
            missing_value = field.missing_value

            # Manipulate fixture obj to have missing value for this field
            field.set(field.interface(obj), missing_value)

            # Update the widget to reflect that changed value on the obj
            with fake_interaction():
                widget.update()

            # Use the widget to retrieve the value - but turn it into a
            # field value using the field's DataConverter, in order to
            # compare it to missing value.
            dc = IDataConverter(widget)
            field_value_from_widget = dc.toFieldValue(widget.value)

            if isinstance(widget, SingleCheckBoxWidget):
                # Boolean fields handled by SingleCheckBoxWidgets are funny:
                # Their fields' missing value is None, which ends up
                # as a widget.value of empty list [], which
                # IDataConverter.toFieldValue() then turns into False.
                #
                # In other words, there isn't really a concept of missing
                # values for booleans - MV will always end up being
                # considered the same as False.
                if field_value_from_widget is False:
                    field_value_from_widget = None

            if isinstance(field, List) and isinstance(widget, CheckBoxWidget):
                # zope.schema.List is weird too - it gets rendered using
                # a CheckBoxWidget.
                missing_value = []

            self.assertEqual(
                missing_value, field_value_from_widget,
                'Unexpectedly got %r instead of missing value %r '
                'from widget %r (for an %r object) ' % (
                    field_value_from_widget, missing_value,
                    widget, obj.portal_type))
Example #31
0
def dexterity_update(obj, request=None):
    """
    Utility method to update the fields of all the schemas of the Dexterity
    object 'obj'.
    """
    modified = defaultdict(list)
    if not request:
        request = obj.REQUEST
    # Call processInputs to decode strings to unicode, otherwise the
    # z3c.form dataconverters complain.
    processInputs(request)
    errors = []
    for schema in get_dexterity_schemas(context=obj):
        for name in getFieldNames(schema):
            # Only update fields which are included in the form
            # Look specifically for the empty-marker used to mark
            # empty checkboxes
            if name not in request.form and \
               '%s-empty-marker' % name not in request.form:
                continue
            field = schema[name]
            autoform_widgets = schema.queryTaggedValue(WIDGETS_KEY, default={})
            if name in autoform_widgets:
                widget = autoform_widgets[name]
                if not isinstance(widget, ParameterizedWidget):
                    widget = ParameterizedWidget(widget)
                widget = widget(field, request)
            else:
                widget = component.getMultiAdapter((field, request),
                                                   IFieldWidget)

            widget.context = obj
            value = field.missing_value
            widget.update()
            try:
                raw = widget.extract()
            except MultipleErrors, e:
                errors.append(e)
                log.warn("Multiple errors while extracting field: %s" % name)
                continue

            if raw is NOT_CHANGED:
                continue

            if raw is NO_VALUE:
                continue

            if (IRichTextValue.providedBy(raw)
                    and api.portal.get_registry_record(
                        'ploneintranet.workspace.sanitize_html')):
                sanitized = RichTextValue(raw=sanitize_html(
                    safe_unicode(raw.raw)),
                                          mimeType=raw.mimeType,
                                          outputMimeType=raw.outputMimeType)
                if sanitized.raw != raw.raw:
                    log.info(
                        'The HTML content of field "{}" on {} was sanitised.'.
                        format(  # noqa
                            name, obj.absolute_url()))
                    raw = sanitized

            if isinstance(field, TextLine):
                # textLines must not contain line breaks (field contraint)
                # to prevent a ConstraintNotSatisfied error in `toFieldValue`
                raw = u" ".join(safe_unicode(raw).splitlines())

            try:
                value = IDataConverter(widget).toFieldValue(safe_unicode(raw))
            except Exception, exc:
                log.warn("Error in converting value for %s: %s (%s)" %
                         (name, raw, str(exc)))
                raise exc

            try:
                field.validate(value)
            except interfaces.RequiredMissing, e:
                errors.append(e)
                log.warn("Required field have missing value: %s" % name)
    def create_content(self, *args, **kwargs):
        """Create content and return its UID"""
        # XXX: Because kwargs are only supported with robotframework >= 2.8.3,
        # we must parse them here to support robotframework < 2.8.3.
        for arg in [x for x in args if '=' in x]:
            name, value = arg.split('=', 1)
            kwargs[name] = value

        assert 'type' in kwargs, u"Keyword arguments must include 'type'."
        portal = getSite()
        if 'container' in kwargs:
            pc = getToolByName(portal, 'portal_catalog')
            uid_or_path = kwargs.pop('container')
            uid_results =\
                pc.unrestrictedSearchResults(UID=uid_or_path)
            path_results = \
                pc.unrestrictedSearchResults(
                    path={'query': uid_or_path.rstrip('/'), 'depth': 0})
            container =\
                (uid_results or path_results)[0]._unrestrictedGetObject()
        else:
            container = portal

        # Pre-fill Image-types with random content
        if kwargs.get('type') == 'Image' and not 'image' in kwargs:
            import random
            import StringIO
            from PIL import (
                Image,
                ImageDraw
            )
            img = Image.new('RGB', (random.randint(320, 640),
                                    random.randint(320, 640)))
            draw = ImageDraw.Draw(img)
            draw.rectangle(((0, 0), img.size), fill=(random.randint(0, 255),
                                                     random.randint(0, 255),
                                                     random.randint(0, 255)))
            del draw

            kwargs['image'] = StringIO.StringIO()
            img.save(kwargs['image'], 'PNG')
            kwargs['image'].seek(0)

        id_ = kwargs.pop('id', None)
        type_ = kwargs.pop('type')

        content = None
        if HAS_DEXTERITY:
            # The title attribute for Dexterity types needs to be unicode
            if 'title' in kwargs and isinstance(kwargs['title'], str):
                kwargs['title'] = kwargs['title'].decode('utf-8')
            from plone.dexterity.interfaces import IDexterityFTI
            from plone.dexterity.utils import createContentInContainer
            try:
                getUtility(IDexterityFTI, name=type_)
                content = createContentInContainer(container, type_, **kwargs)
                if id_ is not None and content.id != id_:
                    container.manage_renameObject(content.id, id_)
            except ComponentLookupError:
                pass

        if HAS_DEXTERITY and content:
            # For dexterity-types, we need a second pass to fill all fields
            # using their widgets to get e.g. RichText-values created
            # correctly.
            fti = getUtility(IDexterityFTI, name=type_)
            schema = fti.lookupSchema()
            fields = {}
            for name in schema:
                fields[name] = schema[name]
            for schema in getAdditionalSchemata(portal_type=type_):
                for name in schema:
                    fields[name] = schema[name]
            for name, field in fields.items():
                widget = queryMultiAdapter((field, getRequest()), IFieldWidget)
                if widget and name in kwargs:
                    if not IFromUnicode.providedBy(field):
                        value = kwargs[name]
                    elif isinstance(kwargs[name], unicode):
                        value = kwargs[name]
                    else:
                        value = unicode(str(kwargs[name]), 'utf-8',
                                        errors='ignore')
                    converter = IDataConverter(widget)
                    dm = queryMultiAdapter((content, field), IDataManager)
                    if dm:
                        dm.set(converter.toFieldValue(value))

        if content is None:
            if id_ is None:
                normalizer = queryUtility(IURLNormalizer)
                id_ = normalizer.normalize(kwargs['title'])

            # It must be Archetypes based content:
            content = container[container.invokeFactory(type_, id_, **kwargs)]
            content.processForm()

        return IUUID(content)
Example #33
0
 def updateWidgets(self):
     super(UpdateMetadataForm, self).updateWidgets()
     widget = self.widgets['issuer']
     value = api.user.get_current().getId()
     widget.value = IDataConverter(widget).toWidgetValue(value)