Source code for xsdata.codegen.utils

import sys
from typing import Optional

from xsdata.codegen.models import Attr
from xsdata.codegen.models import Class
from xsdata.codegen.models import Extension
from xsdata.codegen.models import Restrictions
from xsdata.utils import text


[docs]class ClassUtils: """General reusable utils methods that didn't fit anywhere else."""
[docs] @classmethod def copy_attributes(cls, source: Class, target: Class, extension: Extension): """ Copy the attributes and inner classes from the source class to the target class and remove the extension that links the two classes together. The new attributes are prepended in the list unless if they are supposed to be last in a sequence. """ prefix = text.prefix(extension.type.name) target.extensions.remove(extension) target_attr_names = {text.suffix(attr.name) for attr in target.attrs} index = 0 for attr in source.attrs: if text.suffix(attr.name) not in target_attr_names: clone = cls.clone_attribute(attr, extension.restrictions, prefix) if attr.index == sys.maxsize: target.attrs.append(clone) continue target.attrs.insert(index, clone) index += 1 cls.copy_inner_classes(source, target)
[docs] @classmethod def copy_group_attributes(cls, source: Class, target: Class, attr: Attr): """Copy the attributes and inner classes from the source class to the target class and remove the group attribute that links the two classes together.""" index = target.attrs.index(attr) target.attrs.pop(index) prefix = text.prefix(attr.name) for source_attr in source.attrs: clone = cls.clone_attribute(source_attr, attr.restrictions, prefix) target.attrs.insert(index, clone) index += 1 cls.copy_inner_classes(source, target)
[docs] @classmethod def copy_extensions(cls, source: Class, target: Class, extension: Extension): """Copy the extensions from the source class to the target class and merge the restrictions from the extension that linked the two classes together.""" for ext in source.extensions: clone = ext.clone() clone.restrictions.merge(extension.restrictions) target.extensions.append(clone)
[docs] @classmethod def clone_attribute( cls, attr: Attr, restrictions: Restrictions, prefix: Optional[str] = None ) -> Attr: """ Clone the given attribute and merge its restrictions with the given instance. Prepend the given namespace prefix to the attribute name if available. """ 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
[docs] @classmethod def copy_inner_classes(cls, source: Class, target: Class): """ Copy safely inner classes from source to target class. Checks: 1. Inner is the target class, skip and mark as self reference 2. Inner with same name exists, skip """ for inner in source.inner: if inner is target: for attr in target.attrs: for attr_type in attr.types: if attr_type.forward and attr_type.name == inner.name: attr_type.circular = True elif not any(existing.name == inner.name for existing in target.inner): clone = inner.clone() clone.package = target.package clone.module = target.module target.inner.append(clone)