def queryCatalog(self, limit): """ """ querybuilder = QueryBuilder(self, self.request) if not hasattr(self.data, 'sort_on'): self.data.sort_on = 'effective' if not hasattr(self.data, 'sort_order'): self.data.sort_order = False if not hasattr(self.data, 'sort_folderorder'): self.data.sort_folderorder = False sort_order = 'descending' if self.data.sort_order else 'ascending' sort_on = self.data.sort_on if self.data.sort_folderorder: sort_on = 'getObjPositionInParent' query = list(self.data.query) if ICollection.providedBy(self.context): query += self.context.query and self.context.query or [] parent = aq_parent(aq_inner(self.context)) if ICollection.providedBy(parent): query += parent.query and parent.query or [] return querybuilder(query=query, sort_on=sort_on, sort_order=sort_order, limit=limit)
def get_collection_schema_from_interface_schema(self, schema): collection = {} for name in schema: if IDate.providedBy(schema[name]) or \ IDatetime.providedBy(schema[name]): collection['field.'+name] = 'time' elif IDecimal.providedBy(schema[name]) or \ IFloat.providedBy(schema[name]) or \ IInt.providedBy(schema[name]): collection['field.'+name] = 'number' elif IBool.providedBy(schema[name]): collection['field.'+name] = 'bool' elif ICollection.providedBy(schema[name]): if not ICollection.providedBy(schema[name].value_type) and not \ IDict.providedBy(schema[name].value_type): collection['field.'+name] = 'array' elif IDict.providedBy(schema[name]): if IText.providedBy(schema[name].key_type) and \ IText.providedBy(schema[name].value_type): collection['field.'+name] = 'array' # this is a pretty weak check for a IP address field. We might want # to update this to look for a field validator based on the ipaddress package # or mark this field with a special interface indicating it is an # IP address elif IDottedName.providedBy(schema[name]) and \ (schema[name].min_dots == schema[name].max_dots == 3): collection['field.'+name] = 'cidr' elif IText.providedBy(schema[name]) or \ INativeString.providedBy(schema[name]): collection['field.'+name] = 'string' return collection
def _handleSave(self, action, msg='Saved form data'): self.save_attempt = True data, errors = self.extractData() if errors or IFormDefinition.providedBy(self.context) or self.saved: return False # just validate if errors, or if context if defn if not self.saved: result = {} # submitted data. k: group name; v: dict of name/value group_keys = [] for group in self.groups: groupdata = {} form_group_data = group.extractData()[0] for name, _field in group.fields.items(): group_keys.append(name) fieldname = _field.field.__name__ default = getattr(_field.field, 'default', None) field_data = form_group_data.get(name, default) if ICollection.providedBy(_field.field): if isinstance(_field.field.value_type, DictRow): is_nonempty_row = lambda v: any(v.values()) field_data = filter(is_nonempty_row, field_data) groupdata[fieldname] = field_data result[group.__name__] = groupdata # filter default fieldset values, ignore group values in data dict: result[''] = dict([(k, v) for k, v in data.items() if k not in group_keys]) self._saveResult(result) self.saved = True history_log(self.context, message=msg, set_modified=True) notify(ObjectModifiedEvent(self.context)) transaction.get().note(msg) self._status.addStatusMessage('Saved form data', type='info') return True
def valueToElement(field, value, name=None, force=False): """Create and return an element that describes the given value, which is assumed to be valid for the given field. If name is given, this will be used as the new element name. Otherwise, the field's __name__ attribute is consulted. If force is True, the value will always be written. Otherwise, it is only written if it is not equal to field.missing_value. """ if name is None: name = field.__name__ child = etree.Element(name) if value is not None and (force or value != field.missing_value): if IDict.providedBy(field): key_converter = IToUnicode(field.key_type) for k, v in value.items(): list_element = valueToElement(field.value_type, v, 'element', force) list_element.attrib['key'] = key_converter.toUnicode(k) child.append(list_element) elif ICollection.providedBy(field): for v in value: list_element = valueToElement(field.value_type, v, 'element', force) child.append(list_element) else: converter = IToUnicode(field) child.text = converter.toUnicode(value) return child
def import_node_for_field(self, field, child): value = None # If we have a collection, we need to look at the value_type. # We look for <element>value</element> child nodes and get the # value from there if ICollection.providedBy(field): value_type = field.value_type value = [] for element in child.childNodes: if element.nodeName != 'element': continue value.append(self.import_node_for_field(value_type, element)) elif IObject.providedBy(field): value = {} for element in child.childNodes: if element.nodeName != 'property': continue property_key = self.extract_text(element.attributes['name']) property_value = self.import_node_for_field(field.schema[property_key], element) value[property_key] = property_value elif IChoice.providedBy(field): # Choice fields can be optional, so treat an empty contents as None value = self.extract_text(child) if not value: value = None else: value = self.from_unicode(field, value) else: # Otherwise, just get the value of the <property /> node value = self.extract_text(child) if not (field.getName() == 'root' and value in ['', '/']): value = self.from_unicode(field, value) value = self.field_typecast(field, value) return value
def __getattr__(self, name): reg = self.__registry__ if name not in self.__schema__: raise AttributeError(name) field = self.__schema__.get(name) if IObject.providedBy(field): iface = field.schema collection = reg.collectionOfInterface( iface, check=False, factory=ComplexRecordsProxy) if collection.has_key(name): value = collection[name] else: value = _marker elif ICollection.providedBy(field) and \ IObject.providedBy(field.value_type): iface = field.value_type.schema coll_prefix = iface.__identifier__ + '.' + name collection = reg.collectionOfInterface( iface, check=False, prefix=coll_prefix, factory=ComplexRecordsProxy) value = collection.values() if not value: value = _marker else: value = reg.get(self.__prefix__ + name, _marker) if value is _marker: value = self.__schema__[name].missing_value return value
def import_node(self, interface, child): """Import a single <property /> node """ property_name = child.getAttribute('name') field = interface.get(property_name, None) if field is None: return field = field.bind(self.element) value = None # If we have a collection, we need to look at the value_type. # We look for <element>value</element> child nodes and get the # value from there if ICollection.providedBy(field): value_type = field.value_type value = [] for element in child.childNodes: if element.nodeName != 'element': continue element_value = self.extract_text(element) value.append(self.from_unicode(value_type, element_value)) value = self.field_typecast(field, value) # Otherwise, just get the value of the <property /> node else: value = self.extract_text(child) value = self.from_unicode(field, value) field.validate(value) field.set(self.element, value)
def elementToValue(field, element, default=_marker): """Read the contents of an element that is assumed to represent a value allowable by the given field. If converter is given, it should be an IToUnicode instance. If not, the field will be adapted to this interface to obtain a converter. """ value = default if IDict.providedBy(field): key_converter = IFromUnicode(field.key_type) value = OrderedDict() for child in element.iterchildren(tag=etree.Element): if noNS(child.tag.lower()) != 'element': continue parseinfo.stack.append(child) key_text = child.attrib.get('key', None) if key_text is None: k = None else: k = key_converter.fromUnicode(unicode(key_text)) value[k] = elementToValue(field.value_type, child) parseinfo.stack.pop() value = fieldTypecast(field, value) elif ICollection.providedBy(field): value = [] for child in element.iterchildren(tag=etree.Element): if noNS(child.tag.lower()) != 'element': continue parseinfo.stack.append(child) v = elementToValue(field.value_type, child) value.append(v) parseinfo.stack.pop() value = fieldTypecast(field, value) # Unicode else: text = element.text if text is None: value = field.missing_value else: converter = IFromUnicode(field) value = converter.fromUnicode(unicode(text)) # handle i18n if isinstance(value, unicode) and parseinfo.i18n_domain is not None: translate_attr = ns('translate', I18N_NAMESPACE) domain_attr = ns('domain', I18N_NAMESPACE) msgid = element.attrib.get(translate_attr) domain = element.attrib.get(domain_attr, parseinfo.i18n_domain) if msgid: value = Message(msgid, domain=domain, default=value) elif translate_attr in element.attrib: value = Message(value, domain=domain) return value
def import_node(self, interface, child): """Import a single <property /> node """ property_name = child.getAttribute('name') field = interface.get(property_name, None) if field is None: return field = field.bind(self.assignment) value = None # If we have a collection, we need to look at the value_type. # We look for <element>value</element> child nodes and get the # value from there if ICollection.providedBy(field): value_type = field.value_type value = [] for element in child.childNodes: if element.nodeName != 'element': continue element_value = self.extract_text(element) value.append(self.from_unicode(value_type, element_value)) value = self.field_typecast(field, value) # Otherwise, just get the value of the <property /> node else: value = self.extract_text(child) value = self.from_unicode(field, value) try: field.validate(value) except ConstraintNotSatisfied, e: logger.warning('"%s" value doesn\'t satisfy constaints for "%s:%s" field' % \ (value, self.assignment.__name__, field.__name__))
def fixAjaxSelectWidgetDisplayMode(event): if (isinstance(event.widget, AjaxSelectWidget) and event.widget.mode == DISPLAY_MODE and event.widget.vocabulary): # Sanity check field = getattr(event.widget, 'field', None) if ICollection.providedBy(field): field = field.value_type if field is None or not getattr(field, 'vocabularyName', None): # Field doesn't know its vocabulary and SelectWidget cannot be used return # This is crazy! AjaxSelectWidget is based on select widget and # therefore has completely wrong display mode; Here we replace # the widget with SelectWidget, but is it really this hard? tmp = FieldWidget( event.widget.field, SelectWidget(event.widget.request), ) # Do what they do in z3c.form.field update tmp.name = event.widget.name tmp.id = event.widget.id tmp.context = event.widget.context tmp.form = event.widget.form alsoProvides(tmp, IContextAware, IFormAware) tmp.ignoreContext = event.widget.ignoreContext tmp.ignoreRequest = event.widget.ignoreRequest tmp.showDefault = event.widget.showDefault tmp.mode = event.widget.mode event.widget.__class__ = SelectWidget event.widget.__dict__ = tmp.__dict__ event.widget.update()
def __setattr__(self, name, value): if name in self.__schema__: reg = self.__registry__ field = self.__schema__.get(name) if IObject.providedBy(field): iface = field.schema collection = reg.collectionOfInterface( iface, check=False, factory=ComplexRecordsProxy) collection[name] = value elif ICollection.providedBy(field) and \ IObject.providedBy(field.value_type): iface = field.value_type.schema # All tuple items are stored as records under # the coll_prefix prefix: coll_prefix = iface.__identifier__ + '.' + name collection = reg.collectionOfInterface( iface, check=False, prefix=coll_prefix, factory=ComplexRecordsProxy) # Clear collection before adding/updating in case of deletes. collection.clear() for idx, val in enumerate(value): # val is our obj created by the z3cform factory collection['r' + str(idx)] = val else: full_name = self.__prefix__ + name if full_name not in reg: raise AttributeError(name) reg[full_name] = value else: self.__dict__[name] = value
def _load_widget_data(self): _marker = object() data = aq_base(self.context).data groups = dict((g.__name__, g) for g in self.groups) groupnames = [''] + groups.keys() for groupname in groupnames: group_data = data.get(groupname, None) if groupname is '': group = self else: group = groups.get(groupname) fieldgroup = self.definition[groupname] # # plone.autoform binds groups really, really late, so # # we are stuck with a GroupFactory object, we need to # # call it to get the actual group, then replace the # # group factory with it once we have manipulated # # any widget values: if IGroupFactory.providedBy(group): idx = self.groups.index(group) actual_group = group(self.context, self.request, self) self.groups[idx] = group = actual_group group.update() # will populate group.widgets if group_data and fieldgroup.group_usage == 'grid': data_widget = group.widgets.values()[0] data_widget.value = getattr(group_data, 'data', []) continue if group_data is not None: for formfield in group.fields.values(): schema_field = formfield.field widgetname = formfield.__name__ fieldname = schema_field.__name__ v = getattr(group_data, fieldname, _marker) if v is not _marker: widget = group.widgets.get(widgetname) conv = getMultiAdapter( (schema_field, widget), IDataConverter, ) if not IDataGridField.providedBy(widget): v = conv.toWidgetValue(v) widget.value = v if hasattr(widget, 'update'): # may be necessary to copy value to other state, # as is the case with radio button widgets widget.update() # multiple collection like set/list (multi-choice) # has issues where SequenceWidget wants to reset # widget.value during update... so we have to # check the value (ugly hack) and also re-set the # value for the display widget: if ICollection.providedBy(schema_field): widget.value = v if v: term_item = [ t for t in widget.items if t.get('value') == v[0] ][0] term_item['checked'] = True
def initialize(self): """Initialize the view class.""" fieldId = self.request.get('fieldId', '').split('-')[-1] typeOrDottedname = self.request.get('typeOrDottedname') context = aq_inner(self.context) if typeOrDottedname == context.portal_type and shasattr( context, 'Schema'): # Archetype field = context.Schema().getField(fieldId) self.multivalued = field.multiValued self.widget = field.widget else: fti = queryUtility(IDexterityFTI, name=typeOrDottedname) if fti is None: # Must be a standalone z3c.form forms then. klass = utils.resolveDottedName(typeOrDottedname) field = klass(self.context, self.request).fields.get(fieldId).field self.widget = FieldWidget( field, UserAndGroupSelectionWidget(field, self.request)) self.multivalued = ICollection.providedBy(field) else: # Dexterity schema = fti.lookupSchema() field = schema.get(fieldId) if field is None: # The field might be defined in a behavior schema. # Get the behaviors from either the context or the # portal_type (but not both at the same time). if self.request.get('ignoreContext'): context = None portal_type = typeOrDottedname else: portal_type = None for behavior_schema in \ utils.getAdditionalSchemata(context, portal_type): if behavior_schema is not None: field = behavior_schema.get(fieldId) if field is not None: break self.widget = FieldWidget( field, UserAndGroupSelectionWidget(field, self.request)) self.multivalued = ICollection.providedBy(field) self.memberlookup = MemberLookup(self.context, self.request, self.widget)
def update(self): super(AjaxSelectWidget, self).update() field = getattr(self, 'field', None) if ICollection.providedBy(self.field): field = self.field.value_type if (not self.vocabulary and field is not None and getattr(field, 'vocabularyName', None)): self.vocabulary = field.vocabularyName
def field_info(self, field): is_col = ICollection.providedBy(field) vtype = field.value_type.__class__.__name__ if is_col else None return { 'name': field.__name__, 'title': field.title, 'type': field.__class__.__name__, 'value_type': vtype }
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
def initialize(self): """Initialize the view class.""" fieldId = self.request.get('fieldId','').split('-')[-1] typeOrDottedname = self.request.get('typeOrDottedname') context = aq_inner(self.context) if typeOrDottedname == context.portal_type and shasattr(context, 'Schema'): # Archetype field = context.Schema().getField(fieldId) self.multivalued = field.multiValued self.widget = field.widget else: fti = queryUtility(IDexterityFTI, name=typeOrDottedname) if fti is None: # Must be a standalone z3c.form forms then. klass = utils.resolveDottedName(typeOrDottedname) field = klass(self.context, self.request).fields.get(fieldId).field self.widget = FieldWidget(field, UserAndGroupSelectionWidget(field, self.request)) self.multivalued = ICollection.providedBy(field) else: # Dexterity schema = fti.lookupSchema() field = schema.get(fieldId) if field is None: # The field might be defined in a behavior schema. # Get the behaviors from either the context or the # portal_type (but not both at the same time). if self.request.get('ignoreContext'): context = None portal_type = typeOrDottedname else: portal_type = None for behavior_schema in \ utils.getAdditionalSchemata(context, portal_type): if behavior_schema is not None: field = behavior_schema.get(fieldId) if field is not None: break self.widget = FieldWidget(field, UserAndGroupSelectionWidget(field, self.request)) self.multivalued = ICollection.providedBy(field) self.memberlookup = MemberLookup(self.context, self.request, self.widget)
def schema_type(description): name = description.__class__.__name__ modulename = description.__class__.__module__ if modulename.startswith('zope.schema'): # We hide the _bootstrap modulename = 'zope.schema' field_type = ':py:class:`%s<%s.%s>`' % (name, modulename, name) if ICollection.providedBy(description): field_type += ' of %s' % schema_type(description.value_type) return field_type
def test_fieldref_interfaces(self): from plone.registry import field, FieldRef from plone.registry.interfaces import IFieldRef from zope.schema.interfaces import ICollection listField = field.List(value_type=field.ASCIILine()) ref = FieldRef('some.record', listField) self.assertTrue(ICollection.providedBy(ref)) self.assertTrue(IFieldRef.providedBy(ref))
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(RelatedItemsWidget, self)._base_args() args['name'] = self.name args['value'] = self.value args.setdefault('pattern_options', {}) 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 vocabulary_name = self.vocabulary 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 args['pattern_options'] = dict_merge( get_relateditems_options( view_context, args['value'], self.separator, vocabulary_name, self.vocabulary_view, field_name, ), args['pattern_options']) if (not self.vocabulary_override and field and getattr(field, 'vocabulary', None)): # widget vocab takes precedence over field form_url = self.request.getURL() source_url = '{0:s}/++widget++{1:s}/@@getSource'.format( form_url, self.name) args['pattern_options']['vocabularyUrl'] = source_url return args
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
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
def update(self): super(RelatedItemsWidget, self).update() field = getattr(self, 'field', None) if ICollection.providedBy(self.field): field = self.field.value_type if (not self.vocabulary and field is not None and getattr(field, 'vocabularyName', None)): self.vocabulary = field.vocabularyName self.vocabulary_override = True else: self.vocabulary = 'plone.app.vocabularies.Catalog'
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
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
def __call__(self, context, request): # Sequence widget factory if ICollection.providedBy(context): args = (context, context.value_type, request) + self.args # Vocabulary widget factory elif IChoice.providedBy(context): args = (context, context.vocabulary, request) + self.args # Regular widget factory else: args = (context, request) + self.args return self._create(args)
def _indexer_value(v, fieldtype=None): """General value normalizer for indexed values""" # check datetime, then date, order matters: if isinstance(v, datetime.datetime): return int(time.mktime(v.timetuple())) # timetuple has 1s resolution if isinstance(v, datetime.date): return v.toordinal() if v is None and ICollection.implementedBy(fieldtype): # default value is empty list/set/tuple/dict respective to fieldtype return fieldtype._type() # _type is non-tuple type for collections elif v is None: # avoid range query side effects of None key for index btrees return float('inf') # sentinel value return v
def update(self): super(RelatedItemsWidget, self).update() field = getattr(self, 'field', None) if ICollection.providedBy(self.field): field = self.field.value_type if ( not self.vocabulary and field is not None and getattr(field, 'vocabularyName', None) ): self.vocabulary = field.vocabularyName self.vocabulary_override = True else: self.vocabulary = 'plone.app.vocabularies.Catalog'
def valueToElement(field, value, name=None, force=False): """Create and return an element that describes the given value, which is assumed to be valid for the given field. If name is given, this will be used as the new element name. Otherwise, the field's __name__ attribute is consulted. If force is True, the value will always be written. Otherwise, it is only written if it is not equal to field.missing_value. """ if name is None: name = field.__name__ child = etree.Element(name) if value is not None and (force or value != field.missing_value): if IDict.providedBy(field): key_converter = IToUnicode(field.key_type) for k, v in sorted(value.items()): list_element = valueToElement(field.value_type, v, 'element', force) list_element.attrib['key'] = key_converter.toUnicode(k) child.append(list_element) elif ICollection.providedBy(field): if ISet.providedBy(field): # Serliazation should be consistent even if value was not really a set value = sorted(value) for v in value: list_element = valueToElement(field.value_type, v, 'element', force) child.append(list_element) else: converter = IToUnicode(field) child.text = converter.toUnicode(value) # handle i18n if isinstance(value, Message): child.set(ns('domain', I18N_NAMESPACE), value.domain) if not value.default: child.set(ns('translate', I18N_NAMESPACE), '') else: child.set(ns('translate', I18N_NAMESPACE), child.text) child.text = converter.toUnicode(value.default) return child
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
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(RelatedItemsWidget, self)._base_args() args['name'] = self.name args['value'] = self.value args.setdefault('pattern_options', {}) 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 vocabulary_name = self.vocabulary if not vocabulary_name: if field is not None and field.vocabularyName: vocabulary_name = field.vocabularyName else: vocabulary_name = 'plone.app.vocabularies.Catalog' field_name = self.field and self.field.__name__ or None args['pattern_options'] = dict_merge( get_relateditems_options(self.context, args['value'], self.separator, vocabulary_name, self.vocabulary_view, field_name), args['pattern_options']) if not self.vocabulary: # widget vocab takes precedence over field 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 return args
def elementToValue(field, element, default=_marker): """Read the contents of an element that is assumed to represent a value allowable by the given field. If converter is given, it should be an IToUnicode instance. If not, the field will be adapted to this interface to obtain a converter. """ value = default if IDict.providedBy(field): key_converter = IFromUnicode(field.key_type) value = {} for child in element: if noNS(child.tag.lower()) != 'element': continue key_text = child.attrib.get('key', None) if key_text is None: k = None else: k = key_converter.fromUnicode(unicode(key_text)) value[k] = elementToValue(field.value_type, child) value = fieldTypecast(field, value) elif ICollection.providedBy(field): value = [] for child in element: if noNS(child.tag.lower()) != 'element': continue v = elementToValue(field.value_type, child) value.append(v) value = fieldTypecast(field, value) # Unicode else: text = element.text if text is None: value = field.missing_value else: converter = IFromUnicode(field) value = converter.fromUnicode(unicode(text)) return value
def extract_fields(fields, params): for name, field in fields: value = params.get(name) if value is None: yield value elif ICollection.providedBy(field): if not isinstance(value, Iterable): value = [value] yield value else: if (isinstance(value, Iterable) and not isinstance(value, (str, bytes))): value = value[0] if hasattr(field, 'fromUnicode'): value = field.fromUnicode(value) yield value
def get_vocabulary(self): widget = self.context field = widget.field.bind(widget.context) # check field's write permission info = mergedTaggedValueDict(field.interface, WRITE_PERMISSIONS_KEY) permission_name = info.get(field.__name__, "cmf.ModifyPortalContent") permission = queryUtility(IPermission, name=permission_name) if permission is None: permission = getUtility(IPermission, name="cmf.ModifyPortalContent") if not getSecurityManager().checkPermission(permission.title, self.get_context()): raise VocabLookupException("Vocabulary lookup not allowed.") if ICollection.providedBy(field): return field.value_type.vocabulary else: return field.vocabulary
def get_vocabulary(self): widget = self.context field = widget.field.bind(widget.context) # check field's write permission info = mergedTaggedValueDict(field.interface, WRITE_PERMISSIONS_KEY) permission_name = info.get(field.__name__, 'cmf.ModifyPortalContent') permission = queryUtility(IPermission, name=permission_name) if permission is None: permission = getUtility(IPermission, name='cmf.ModifyPortalContent') if not getSecurityManager().checkPermission(permission.title, self.get_context()): raise VocabLookupException('Vocabulary lookup not allowed.') if ICollection.providedBy(field): return field.value_type.vocabulary return field.vocabulary
def import_node(self, interface, child): """Import a single <property /> node """ property_name = child.getAttribute('name') field = interface.get(property_name, None) if field is None: return field = field.bind(self.assignment) value = None # If we have a collection, we need to look at the value_type. # We look for <element>value</element> child nodes and get the # value from there if ICollection.providedBy(field): value_type = field.value_type value = [] for element in child.childNodes: if element.nodeName != 'element': continue element_value = self.extract_text(element) value.append(self.from_unicode(value_type, element_value)) value = self.field_typecast(field, value) # Otherwise, just get the value of the <property /> node else: value = self.extract_text(child) if not (field.getName() == 'root' and value in ['', '/']): value = self.from_unicode(field, value) if field.getName() == 'root' and value in ['', '/']: # these valid values don't pass validation of SearchableTextSourceBinder field.set(self.assignment, value) else: # I don't care if it's raised on a path... try: field.validate(value) except ConstraintNotSatisfied: if type(field) == Choice and ISource.providedBy(field.source): pass else: raise field.set(self.assignment, value)
def export_field(self, doc, field): """Turn a zope.schema field into a node and return it """ field = field.bind(self.assignment) value = field.get(self.assignment) child = doc.createElement('property') child.setAttribute('name', field.__name__) if value is not None: if ICollection.providedBy(field): for e in value: list_element = doc.createElement('element') list_element.appendChild(doc.createTextNode(str(e))) child.appendChild(list_element) else: child.appendChild(doc.createTextNode(unicode(value))) return child
def export_field(self, doc, field): """Turn a zope.schema field into a node and return it """ field = field.bind(self.assignment) value = field.get(self.assignment) child = doc.createElement('property') child.setAttribute('name', field.__name__) if value is not None: if ICollection.providedBy(field): for e in value: list_element = doc.createElement('element') list_element.appendChild(doc.createTextNode(str(e))) child.appendChild(list_element) else: child.appendChild(doc.createTextNode(six.text_type(value))) return child
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(RelatedItemsWidget, self)._base_args() args["name"] = self.name args["value"] = self.value args.setdefault("pattern_options", {}) 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 field is not None and field.vocabularyName: vocabulary_name = field.vocabularyName field_name = self.field and self.field.__name__ or None args["pattern_options"] = dict_merge( get_relateditems_options( self.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 return args
def export_sub_field(self, doc, parent, field, value): """Turn a zope.schema field into a node and return it """ if value is not None: if ICollection.providedBy(field): for e in value: list_element = doc.createElement('element') self.export_sub_field(doc, list_element, field.value_type, e) parent.appendChild(list_element) elif IObject.providedBy(field): for name, sub_field in field.schema.namesAndDescriptions(): sub_value = value.get(name) list_element = doc.createElement('property') list_element.setAttribute('name', name) self.export_sub_field(doc, list_element, sub_field, sub_value) parent.appendChild(list_element) else: parent.appendChild(doc.createTextNode(unicode(value))) return parent
def convertRecord(record, schema): """Converts the QueryRecords from a query result into a dict based on the schema. """ sf_fields = schema.queryTaggedValue('salesforce.fields', {}) sf_relationships = schema.queryTaggedValue('salesforce.relationships', {}) sf_subqueries = schema.queryTaggedValue('salesforce.subqueries', {}) d = {} for fname in schema: field = schema[fname] if fname in sf_fields: # Determine the 'path' to the field value. field_parts = sf_fields[fname].split('.') if fname in sf_relationships.keys(): field_parts = sf_relationships[fname].split('.') + field_parts # Try to get a corresponding value from the record. try: value = valueFromRecord(record, field_parts) except KeyError: continue d[fname] = convertToSchemaValue(field, value) elif fname in sf_relationships: if ICollection.providedBy(field) and IObject.providedBy(field.value_type): subschema = field.value_type.schema subvalues = [] for subrecord in valueFromRecord(record, sf_relationships[fname].split('.')): subvalues.append(convertRecord(subrecord, subschema)) d[fname] = subvalues else: pass elif fname in sf_subqueries: # custom query, we don't know how to find the relevant value on # the record so we just give the converter the whole record and # let it do its thing. # (Things will blow up if there isn't a custom converter!) d[fname] = convertToSchemaValue(field, record) return d
def common_widget_updates(context): """ Given a context, update field widgets for it. Context May be any z3c.form instance or a field group contained within. """ # form field filter definition: vtype = lambda formfield: getattr(formfield.field, 'value_type', None) use_vocab = lambda v: hasattr(v, '__len__') and hasattr(v, '__iter__') is_choice = lambda formfield: IChoice.providedBy(formfield.field) v_choice = lambda formfield: IChoice.providedBy(vtype(formfield)) is_collection = lambda formfield: ICollection.providedBy(formfield.field) is_multi = lambda formfield: is_collection(formfield) and v_choice( formfield) # noqa is_date = lambda formfield: IDate.providedBy(formfield.field) is_bool = lambda formfield: IBool.providedBy(formfield.field) # filtered lists of form fields by type formfields = context.fields.values() choicefields = filter(is_choice, formfields) multifields = filter(is_multi, formfields) datefields = filter(is_date, formfields) boolfields = filter(is_bool, formfields) for formfield in choicefields: vocab = formfield.field.vocabulary if use_vocab(vocab) and len(vocab) <= 6: formfield.widgetFactory = RadioFieldWidget for formfield in multifields: vocab = formfield.field.value_type.vocabulary if use_vocab(vocab) and len(vocab) <= 16: formfield.widgetFactory = CheckBoxFieldWidget for formfield in datefields: formfield.widgetFactory = TypeADateFieldWidget for formfield in boolfields: formfield.widgetFactory = RadioFieldWidget
def common_widget_updates(context): """ Given a context, update field widgets for it. Context May be any z3c.form instance or a field group contained within. """ # form field filter definition: vtype = lambda formfield: getattr(formfield.field, 'value_type', None) use_vocab = lambda v: hasattr(v, '__len__') and hasattr(v, '__iter__') is_choice = lambda formfield: IChoice.providedBy(formfield.field) v_choice = lambda formfield: IChoice.providedBy(vtype(formfield)) is_collection = lambda formfield: ICollection.providedBy(formfield.field) is_multi = lambda formfield: is_collection(formfield) and v_choice(formfield) # noqa is_date = lambda formfield: IDate.providedBy(formfield.field) is_bool = lambda formfield: IBool.providedBy(formfield.field) # filtered lists of form fields by type formfields = context.fields.values() choicefields = filter(is_choice, formfields) multifields = filter(is_multi, formfields) datefields = filter(is_date, formfields) boolfields = filter(is_bool, formfields) for formfield in choicefields: vocab = formfield.field.vocabulary if use_vocab(vocab) and len(vocab) <= 3: formfield.widgetFactory = RadioFieldWidget for formfield in multifields: vocab = formfield.field.value_type.vocabulary if use_vocab(vocab) and len(vocab) <= 16: formfield.widgetFactory = CheckBoxFieldWidget for formfield in datefields: formfield.widgetFactory = TypeADateFieldWidget for formfield in boolfields: formfield.widgetFactory = RadioFieldWidget
def valueToElement(field, value, name=None, force=False): """Create and return an element that describes the given value, which is assumed to be valid for the given field. If name is given, this will be used as the new element name. Otherwise, the field's __name__ attribute is consulted. If force is True, the value will always be written. Otherwise, it is only written if it is not equal to field.missing_value. """ if name is None: name = field.__name__ child = ElementTree.Element(name) if value is not None and (force or value != field.missing_value): if IDict.providedBy(field): key_converter = IToUnicode(field.key_type) for k, v in value.items(): list_element = valueToElement(field.value_type, v, 'element', force) list_element.attrib['key'] = key_converter.toUnicode(k) child.append(list_element) elif ICollection.providedBy(field): for v in value: list_element = valueToElement(field.value_type, v, 'element', force) child.append(list_element) else: converter = IToUnicode(field) child.text = converter.toUnicode(value) return child