def build_class_attribute_types(self, target: Class, obj: ElementBase) -> List[AttrType]: """Convert real type and anonymous inner types to an attribute type list.""" types = [ self.build_data_type(target, name) for name in (obj.real_type or "").split(" ") if name ] for inner in self.build_inner_classes(obj): target.inner.append(inner) types.append(AttrType(name=inner.name, forward_ref=True)) if len(types) == 0: types.append(AttrType(name=obj.default_type.code, native=True)) return types
def build_class_attribute_types( self, target: Class, obj: AttributeElement ) -> List[AttrType]: """Convert real type and anonymous inner elements to an attribute type list.""" inner_class = self.build_inner_class(obj) types = [ self.build_data_type(target, name) for name in (obj.real_type or "").split(" ") if name ] if inner_class: target.inner.append(inner_class) types.append(AttrType(name=inner_class.name, forward_ref=True)) if len(types) == 0: types.append(AttrType(name=DataType.STRING.code, native=True)) return types
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 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_type(self, target: Class, attr: Attr, attr_type: AttrType): """Flatten attribute type if it's a simple type otherwise check for circular reference or missing type.""" simple_source = self.find_attr_simple_type(target, attr_type) if simple_source: self.merge_attribute_type(simple_source, target, attr, attr_type) else: complex_source = self.find_attr_type(target, attr_type) if complex_source: attr_type.self_ref = self.class_depends_on( complex_source, target) else: logger.warning("Missing type: %s", attr_type.name) self.reset_attribute_type(attr_type)
def build_data_type(self, target: Class, name: str, index: int = 0, forward_ref: bool = False) -> AttrType: prefix, suffix = text.split(name) native = False namespace = target.ns_map.get(prefix) if Namespace.get_enum(namespace) and DataType.get_enum(suffix): name = suffix native = True return AttrType( name=name, index=index, native=native, forward_ref=forward_ref, )
def test_create_reference_attribute(self): item = ClassFactory.elements(1) actual = ClassUtils.create_reference_attribute(item, QName("foo")) expected = AttrFactory.create( name=item.name, index=0, default=None, types=[AttrType(name=f"{item.source_prefix}:{item.name}")], local_type=item.type.__name__, ) self.assertEqual(expected, actual) actual = ClassUtils.create_reference_attribute( item, item.source_qname("foo")) self.assertEqual(item.name, actual.types[0].name) item.source_namespace = None actual = ClassUtils.create_reference_attribute(item, QName("foo")) self.assertEqual(item.name, actual.types[0].name)
def test_create_mixed_attribute(self): item = ClassFactory.create() ClassUtils.create_mixed_attribute(item) self.assertEqual(0, len(item.attrs)) item = ClassFactory.elements(2, mixed=True) ClassUtils.create_mixed_attribute(item) expected = AttrFactory.create( name="content", index=0, wildcard=True, types=[AttrType(name=DataType.ANY_TYPE.code, native=True)], local_type=TagType.ANY, namespace="##any", ) self.assertEqual(expected, item.attrs[0]) self.assertEqual(3, len(item.attrs)) ClassUtils.create_mixed_attribute(item) self.assertEqual(3, len(item.attrs))
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 reset_attribute_type(cls, attr_type: AttrType): attr_type.name = DataType.STRING.code attr_type.native = True attr_type.self_ref = False attr_type.forward_ref = False