Source code for xsdata.codegen.analyzer
from typing import List
from xsdata.codegen.container import ClassContainer
from xsdata.codegen.models import Class
from xsdata.codegen.sanitizer import ClassSanitizer
from xsdata.codegen.validator import ClassValidator
from xsdata.exceptions import AnalyzerError
[docs]class ClassAnalyzer:
"""Analyzer main responsibility is to orchestrate the processing of the
class list and the selection of the final list of classes that need to be
generated."""
def __init__(self, classes: List[Class]):
self.container = ClassContainer.from_list(classes)
[docs] def process(self) -> List[Class]:
self.pre_process()
self.container.process()
self.post_process()
return self.select_classes()
[docs] def pre_process(self):
ClassValidator(self.container).process()
[docs] def post_process(self):
ClassSanitizer(self.container).process()
[docs] def select_classes(self) -> List[Class]:
"""
Return the qualified classes for code generation.
Return all if no classes are derived from xs:element or
xs:complexType.
"""
classes = list(self.container.iterate())
if any(item.is_complex for item in classes if not item.abstract):
classes = list(
filter(
lambda x: x.is_enumeration or (x.is_complex and not x.abstract),
classes,
)
)
self.validate_references(classes)
return classes
[docs] @classmethod
def class_references(cls, target: Class) -> List:
result = [id(target)]
for attr in target.attrs:
result.append(id(attr))
result.extend(id(attr_type) for attr_type in attr.types)
for extension in target.extensions:
result.append(id(extension))
result.append(id(extension.type))
for inner in target.inner:
result.extend(cls.class_references(inner))
return result
[docs] @classmethod
def validate_references(cls, classes: List[Class]):
"""Validate all code gen objects are not cross referenced."""
references = [ref for obj in classes for ref in cls.class_references(obj)]
if len(references) != len(set(references)):
raise AnalyzerError("Cross references detected!")