Source code for xsdata.models.inspect

from dataclasses import dataclass
from dataclasses import field
from enum import IntEnum
from typing import Any
from typing import Dict
from typing import List
from typing import Optional
from typing import Type

from lxml.etree import QName

from xsdata.models.enums import NamespaceType
from xsdata.models.enums import TagType


[docs]class Tag(IntEnum): TEXT = 1 ATTRIBUTE = 2 ANY_ATTRIBUTE = 3 ELEMENT = 4 ANY_ELEMENT = 5 ROOT = 6 MISC = 7
[docs] @classmethod def from_metadata_type(cls, meta_type: Optional[str]) -> "Tag": return __tag_type_map__.get(meta_type, cls.TEXT)
__tag_type_map__ = { TagType.ATTRIBUTE: Tag.ATTRIBUTE, TagType.ANY_ATTRIBUTE: Tag.ANY_ATTRIBUTE, TagType.ELEMENT: Tag.ELEMENT, TagType.ANY: Tag.ANY_ELEMENT, None: Tag.MISC, }
[docs]@dataclass(frozen=True) class ClassVar: name: str qname: QName types: List[Type] tag: Tag init: bool = True nillable: bool = False dataclass: bool = False sequential: bool = False default: Any = None wild_ns: List[str] = field(default_factory=list) @property def clazz(self): return self.types[0] if self.dataclass else None @property def is_attribute(self): return self.tag == Tag.ATTRIBUTE @property def is_any_attribute(self): return self.tag == Tag.ANY_ATTRIBUTE @property def is_any_element(self): return self.tag == Tag.ANY_ELEMENT @property def is_element(self): return self.tag == Tag.ELEMENT @property def is_list(self): return self.default is list @property def is_text(self): return self.tag == Tag.TEXT @property def namespace(self): return self.qname.namespace
[docs]@dataclass(frozen=True) class ClassMeta: name: str clazz: Type qname: QName mixed: bool nillable: bool vars: Dict[QName, ClassVar] @property def namespace(self): return self.qname.namespace @property def any_text(self) -> Optional[ClassVar]: return next((var for var in self.vars.values() if var.is_text), None) @property def any_attribute(self) -> Optional[ClassVar]: return next((var for var in self.vars.values() if var.is_any_attribute), None) @property def any_element(self) -> Optional[ClassVar]: return next((var for var in self.vars.values() if var.is_any_element), None)
[docs] def get_var(self, qname: QName) -> Optional[ClassVar]: if qname in self.vars: return self.vars[qname] else: return self.get_wild_var(qname)
[docs] def get_wild_var(self, qname: QName) -> Optional[ClassVar]: return next((var for var in self.get_wild_vars(qname)), None)
[docs] def get_matching_wild_var(self, qname: QName, condition): return next((x for x in self.get_wild_vars(qname) if condition(x)), None)
[docs] def get_wild_vars(self, qname: QName): for var in self.vars.values(): if self.matches(var.wild_ns, qname): yield var
[docs] @classmethod def matches(cls, namespaces: List[str], qname: QName) -> bool: return next( (True for namespace in namespaces if cls.match(namespace, qname)), False )
[docs] @classmethod def match(cls, namespace: str, qname: QName): return ( namespace and ( namespace == qname.namespace or namespace == NamespaceType.ANY.value or namespace[0] == "!" and namespace[1:] != qname.namespace ) ) or (not namespace and qname.namespace is None)