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)
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
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
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))
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
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
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')
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
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)
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()
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)
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
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
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
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))
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 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)
def updateWidgets(self): super(UpdateMetadataForm, self).updateWidgets() widget = self.widgets['issuer'] value = api.user.get_current().getId() widget.value = IDataConverter(widget).toWidgetValue(value)