Source code for xsdata.formats.dataclass.models.elements
importitertoolsimportoperatorimportsysfromtypingimportAnyfromtypingimportCallablefromtypingimportDictfromtypingimportIteratorfromtypingimportListfromtypingimportMappingfromtypingimportOptionalfromtypingimportSequencefromtypingimportSetfromtypingimportTuplefromtypingimportTypefromxsdata.formats.converterimportconverterfromxsdata.models.enumsimportNamespaceTypefromxsdata.utilsimportcollectionsfromxsdata.utils.namespacesimportlocal_namefromxsdata.utils.namespacesimporttarget_uriNoneType=type(None)classXmlType:"""Xml node types."""TEXT=sys.intern("Text")ELEMENT=sys.intern("Element")ELEMENTS=sys.intern("Elements")WILDCARD=sys.intern("Wildcard")ATTRIBUTE=sys.intern("Attribute")ATTRIBUTES=sys.intern("Attributes")IGNORE=sys.intern("Ignore")classMetaMixin:"""Use this mixin for unit tests only!!!"""__slots__:Tuple[str,...]=()def__eq__(self,other:Any)->bool:returntuple(self)==tuple(other)def__iter__(self)->Iterator:fornameinself.__slots__:yieldgetattr(self,name)def__repr__(self)->str:params=(f"{name}={getattr(self,name)!r}"fornameinself.__slots__)returnf"{self.__class__.__qualname__}({', '.join(params)})"
[docs]classXmlVar(MetaMixin):""" Class field binding metadata. :param index: Field ordering :param name: Field name :param qname: Qualified name :param types: List of all the supported data types :param init: Include field in the constructor :param mixed: Field supports mixed content type values :param tokens: Field is derived from xs:list :param format: Value format information :param derived: Wrap parsed values with a generic type :param any_type: Field supports dynamic value types :param required: Field is mandatory :param nillable: Field supports nillable content :param sequential: Render values in sequential mode :param list_element: Field is a list of elements :param default: Field default value or factory :param xml_Type: Field xml type :param namespaces: List of the supported namespaces :param elements: Mapping of qname-repeatable elements :param wildcards: List of repeatable wildcards """__slots__=("index","name","qname","types","clazz","init","mixed","factory","tokens_factory","format","derived","any_type","required","nillable","sequential","default","namespaces","elements","wildcards",# Calculated"tokens","list_element","is_text","is_element","is_elements","is_wildcard","is_attribute","is_attributes","namespace_matches","is_clazz_union","local_name",)def__init__(self,index:int,name:str,qname:str,types:Sequence[Type],clazz:Optional[Type],init:bool,mixed:bool,factory:Optional[Callable],tokens_factory:Optional[Callable],format:Optional[str],derived:bool,any_type:bool,required:bool,nillable:bool,sequential:bool,default:Any,xml_type:str,namespaces:Sequence[str],elements:Mapping[str,"XmlVar"],wildcards:Sequence["XmlVar"],**kwargs:Any,):self.index=indexself.name=nameself.qname=qnameself.types=typesself.clazz=clazzself.init=initself.mixed=mixedself.tokens=tokens_factoryisnotNoneself.format=formatself.derived=derivedself.any_type=any_typeself.required=requiredself.nillable=nillableself.sequential=sequentialself.list_element=factoryin(list,tuple)self.default=defaultself.namespaces=namespacesself.elements=elementsself.wildcards=wildcardsself.factory=factoryself.tokens_factory=tokens_factoryself.namespace_matches:Optional[Dict[str,bool]]=Noneself.is_clazz_union=self.clazzandlen(types)>1self.local_name=local_name(qname)self.is_text=Falseself.is_element=Falseself.is_elements=Falseself.is_wildcard=Falseself.is_attribute=Falseself.is_attributes=Falseifxml_type==XmlType.ELEMENTorself.clazz:self.is_element=Trueelifxml_type==XmlType.ELEMENTS:self.is_elements=Trueelifxml_type==XmlType.ATTRIBUTE:self.is_attribute=Trueelifxml_type==XmlType.ATTRIBUTES:self.is_attributes=Trueelifxml_type==XmlType.WILDCARD:self.is_wildcard=Trueelse:self.is_text=True@propertydefelement_types(self)->Set[Type]:return{tpforelementinself.elements.values()fortpinelement.types}
[docs]deffind_choice(self,qname:str)->Optional["XmlVar"]:"""Match and return a choice field by its qualified name."""match=self.elements.get(qname)returnmatchorfind_by_namespace(self.wildcards,qname)
[docs]deffind_value_choice(self,value:Any,check_subclass:bool)->Optional["XmlVar"]:"""Match and return a choice field that matches the given value type."""ifcollections.is_array(value):tp=type(None)ifnotvalueelsetype(value[0])tokens=Truecheck_subclass=Falseelse:tp=type(value)tokens=Falsereturnself.find_type_choice(value,tp,tokens,check_subclass)
[docs]deffind_type_choice(self,value:Any,tp:Type,tokens:bool,check_subclass:bool)->Optional["XmlVar"]:"""Match and return a choice field that matches the given type."""forelementinself.elements.values():ifelement.any_typeortokens!=element.tokens:continueiftpisNoneType:ifelement.nillable:returnelementelifself.match_type(value,tp,element.types,check_subclass):returnelementreturnNone
[docs]defis_optional(self,value:Any)->bool:"""Return whether this var instance is not required and the given value matches the default one."""ifself.required:returnFalseifcallable(self.default):returnself.default()==valuereturnself.default==value
[docs]defmatch_namespace(self,qname:str)->bool:"""Match the given qname to the wildcard allowed namespaces."""ifself.namespace_matchesisNone:self.namespace_matches={}matches=self.namespace_matches.get(qname)ifmatchesisNone:matches=self._match_namespace(qname)self.namespace_matches[qname]=matchesreturnmatches
[docs]classXmlMeta(MetaMixin):""" Class binding metadata. :param clazz: The dataclass type :param qname: The namespace qualified name. :param target_qname: The target namespace qualified name. :param nillable: Specifies whether an explicit empty value can be assigned. :param mixed_content: Has a wildcard with mixed flag enabled :param text: Text var :param choices: List of compound vars :param elements: Mapping of qname-element vars :param wildcards: List of wildcard vars :param attributes: Mapping of qname-attribute vars :param any_attributes: List of wildcard attributes vars """__slots__=("clazz","qname","target_qname","nillable","text","choices","elements","wildcards","attributes","any_attributes",# Calculated"namespace","mixed_content",)def__init__(self,clazz:Type,qname:str,target_qname:Optional[str],nillable:bool,text:Optional[XmlVar],choices:Sequence[XmlVar],elements:Mapping[str,Sequence[XmlVar]],wildcards:Sequence[XmlVar],attributes:Mapping[str,XmlVar],any_attributes:Sequence[XmlVar],**kwargs:Any,):self.clazz=clazzself.qname=qnameself.namespace=target_uri(qname)self.target_qname=target_qnameself.nillable=nillableself.text=textself.choices=choicesself.elements=elementsself.wildcards=wildcardsself.attributes=attributesself.any_attributes=any_attributesself.mixed_content=any(wildcard.mixedforwildcardinself.wildcards)@propertydefelement_types(self)->Set[Type]:return{tpforelementsinself.elements.values()forelementinelementsfortpinelement.types}defget_element_vars(self)->List[XmlVar]:result=list(itertools.chain(self.wildcards,self.choices,*self.elements.values()))ifself.text:result.append(self.text)returnsorted(result,key=get_index)defget_attribute_vars(self)->List[XmlVar]:result=itertools.chain(self.any_attributes,self.attributes.values())returnsorted(result,key=get_index)defget_all_vars(self)->List[XmlVar]:result=list(itertools.chain(self.wildcards,self.choices,self.any_attributes,self.attributes.values(),*self.elements.values(),))ifself.text:result.append(self.text)returnsorted(result,key=get_index)deffind_attribute(self,qname:str)->Optional[XmlVar]:returnself.attributes.get(qname)deffind_any_attributes(self,qname:str)->Optional[XmlVar]:returnfind_by_namespace(self.any_attributes,qname)
[docs]deffind_wildcard(self,qname:str)->Optional[XmlVar]:"""Match the given qualified name to a wildcard and optionally to one of its choice elements."""wildcard=find_by_namespace(self.wildcards,qname)ifwildcardandwildcard.elements:choice=wildcard.find_choice(qname)ifchoice:returnchoicereturnwildcard