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 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 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 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 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 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
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') if key_text is None: k = None else: k = key_converter.fromUnicode(six.text_type(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) elif IChoice.providedBy(field): vocabulary = None try: vcf = getUtility(IVocabularyFactory, field.vocabularyName) vocabulary = vcf(None) except: pass if vocabulary and hasattr(vocabulary, 'by_value'): try: field._type = type(list(vocabulary.by_value.keys())[0]) except: pass value = fieldTypecast(field, element.text) # Unicode else: text = element.text if text is None: value = field.missing_value else: converter = IFromUnicode(field) if isinstance(text, six.binary_type): text = text.decode() else: text = six.text_type(text) value = converter.fromUnicode(text) # handle i18n if isinstance(value, six.string_types) 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