def create_default_attribute(cls, item: Class, extension: Extension): if extension.type.native_code == DataType.ANY_TYPE.code: attr = Attr( name="any_element", local_name="any_element", index=0, wildcard=True, default=list if extension.restrictions.is_list else None, types=[extension.type.clone()], local_type=TagType.ANY, namespace=NamespaceType.ANY.value, restrictions=extension.restrictions.clone(), ) else: attr = Attr( name="value", local_name="value", index=0, default=None, types=[extension.type.clone()], local_type=TagType.EXTENSION, restrictions=extension.restrictions.clone(), ) item.attrs.insert(0, attr) item.extensions.remove(extension)
def sanitize_attribute(cls, attr: Attr): if attr.is_list: attr.fixed = False else: attr.restrictions.sequential = False if attr.is_optional or attr.is_xsi_type: attr.fixed = False attr.default = None
def process_attribute(cls, target: Class, attr: Attr, parents: List[str]): """Normalize attribute properties.""" attr.name = cls.attribute_name(attr.name) attr.display_type = cls.attribute_display_type(attr, parents) attr.default = cls.attribute_default(attr, target.ns_map) attr.xml_type = cls.xml_type_map.get(attr.tag) if attr.local_name: attr.local_name = text.suffix(attr.local_name)
def build_class_attribute(self, target: Class, obj: ElementBase, parent_restrictions: Restrictions): """Generate and append an attribute target to the target class.""" types = self.build_class_attribute_types(target, obj) restrictions = Restrictions.from_element(obj) if obj.class_name in (Tag.ELEMENT, Tag.ANY): restrictions.merge(parent_restrictions) if restrictions.prohibited: return name = obj.real_name target.ns_map.update(obj.ns_map) target.attrs.append( Attr( index=obj.index, name=name, local_name=name, default=obj.default_value, fixed=obj.is_fixed, types=types, tag=obj.class_name, help=obj.display_help, namespace=self.element_namespace(obj), restrictions=restrictions, ))
def clone_attribute(cls, attr: Attr, restrictions: Restrictions, prefix: Optional[str] = None): clone = attr.clone() clone.restrictions.merge(restrictions) if prefix: for attr_type in clone.types: if not attr_type.native and attr_type.name.find(":") == -1: attr_type.name = f"{prefix}:{attr_type.name}" return clone
def create_mixed_attribute(cls, target: Class): if not target.mixed or target.has_wild_attr: return attr = Attr( name="content", local_name="content", index=0, types=[AttrType(name=DataType.ANY_TYPE.code, native=True)], tag=Tag.ANY, namespace=NamespaceType.ANY.value, ) target.attrs.insert(0, attr)
def flatten_attribute_types(self, target: Class, attr: Attr): """ Flatten attribute types by using the source attribute type. Steps: * Skip xsd native types * Detect circular references if no source is found * Skip enumeration types * Overwrite attribute type from source """ types = [] for attr_type in attr.types: source = None if not attr_type.native: type_qname = target.source_qname(attr_type.name) source = self.find_class(type_qname) if source is None: attr_type.self_ref = self.attr_depends_on(attr_type, target) types.append(attr_type) elif self.is_qname(source): types.append(source.extensions[0].type.clone()) elif source.is_enumeration: types.append(attr_type) elif len(source.attrs) == 1: source_attr = source.attrs[0] types.extend(source_attr.types) restrictions = source_attr.restrictions.clone() restrictions.merge(attr.restrictions) attr.restrictions = restrictions self.copy_inner_classes(source, target) else: types.append(AttrType(name=DataType.STRING.code, native=True)) logger.warning("Missing type implementation: %s", source.type.__name__) attr.types = types
def create_reference_attribute(cls, source: Class, qname: QName): prefix = None if qname.namespace != source.source_namespace: prefix = source.source_prefix reference = f"{prefix}:{source.name}" if prefix else source.name return Attr( name=source.name, local_name=source.name, index=0, default=None, types=[AttrType(name=reference)], local_type=source.type.__name__, namespace=source.namespace, )
def flatten_attribute_types(self, target: Class, attr: Attr): """ Loop over the the given attribute types to flatten simple definitions. Notes: * xs:pattern is not yet supported reset all native types to xs:string. * skip over forward references aka inner classes """ for current_type in list(attr.types): if current_type.native: if attr.restrictions.pattern: self.reset_attribute_type(current_type) elif not current_type.forward_ref: self.flatten_attribute_type(target, attr, current_type) attr.types = unique_sequence(attr.types, key="name")
def merge_attribute_type(cls, source: Class, target: Class, attr: Attr, attr_type: AttrType): if len(source.attrs) != 1: logger.warning("Missing implementation: %s", source.type.__name__) cls.reset_attribute_type(attr_type) else: source_attr = source.attrs[0] index = attr.types.index(attr_type) attr.types.pop(index) for source_attr_type in source_attr.types: clone_type = source_attr_type.clone() attr.types.insert(index, clone_type) index += 1 restrictions = source_attr.restrictions.clone() restrictions.merge(attr.restrictions) attr.restrictions = restrictions cls.copy_inner_classes(source, target)