Exemple #1
0
    def create_default_attribute(cls, item: Class, extension: Extension):
        """Add a default value field to the given class based on the extension
        type."""
        if extension.type.native_code == DataType.ANY_TYPE.code:
            attr = Attr(
                name="any_element",
                local_name="any_element",
                index=0,
                default=list if extension.restrictions.is_list else None,
                types=[extension.type.clone()],
                tag=Tag.ANY,
                namespace=NamespaceType.ANY.value,
                restrictions=extension.restrictions.clone(),
            )
        else:
            attr = Attr(
                name="value",
                local_name="value",
                index=0,
                default=None,
                types=[extension.type.clone()],
                tag=Tag.EXTENSION,
                restrictions=extension.restrictions.clone(),
            )

        item.attrs.insert(0, attr)
        item.extensions.remove(extension)
Exemple #2
0
 def create(
     cls,
     name: Optional[str] = None,
     index: Optional[int] = None,
     types: Optional[List[AttrType]] = None,
     choices: Optional[List[Attr]] = None,
     tag: Optional[str] = None,
     namespace: Optional[str] = None,
     default: Any = None,
     fixed: bool = False,
     mixed: bool = False,
     restrictions: Optional[Restrictions] = None,
     **kwargs: Any,
 ) -> Attr:
     name = name or f"attr_{cls.next_letter()}"
     return Attr(
         name=name,
         index=cls.counter if index is None else index,
         types=types or [AttrTypeFactory.native(DataType.STRING)],
         choices=choices or [],
         tag=tag or random.choice(cls.tags),
         namespace=namespace or None,
         default=default or None,
         fixed=fixed,
         mixed=mixed,
         restrictions=restrictions or Restrictions(),
         **kwargs,
     )
Exemple #3
0
    def build_class_attribute(
        cls, target: Class, obj: ElementBase, parent_restrictions: Restrictions
    ):
        """Generate and append an attribute field to the target class."""

        target.ns_map.update(obj.ns_map)
        types = cls.build_class_attribute_types(target, obj)
        restrictions = Restrictions.from_element(obj)

        if obj.class_name in (Tag.ELEMENT, Tag.ANY):
            restrictions.merge(parent_restrictions)

        if restrictions.prohibited:
            return

        name = obj.real_name
        target.attrs.append(
            Attr(
                index=obj.index,
                name=name,
                local_name=name,
                default=obj.default_value,
                fixed=obj.is_fixed,
                types=types,
                tag=obj.class_name,
                help=obj.display_help,
                namespace=cls.element_namespace(obj, target.qname.namespace),
                restrictions=restrictions,
            )
        )
    def process(cls, target: Class):
        """Add or update an existing an xs:anyType derived attribute if the
        target class supports mixed content."""

        if not target.mixed:
            return

        wildcard = first(attr for attr in target.attrs if attr.tag == Tag.ANY)

        if wildcard:
            wildcard.mixed = True
            if not wildcard.is_list:
                wildcard.restrictions.min_occurs = 0
                wildcard.restrictions.max_occurs = sys.maxsize
        else:
            attr = Attr(
                name="content",
                types=[AttrType(qname=str(DataType.ANY_TYPE), native=True)],
                tag=Tag.ANY,
                mixed=True,
                namespace=NamespaceType.ANY_NS,
                restrictions=Restrictions(min_occurs=0,
                                          max_occurs=sys.maxsize),
            )
            target.attrs.insert(0, attr)
Exemple #5
0
    def group_fields(self, target: Class, attrs: List[Attr]):
        """Group attributes into a new compound field."""

        pos = target.attrs.index(attrs[0])
        names = []
        choices = []
        min_occurs = []
        max_occurs = []
        for attr in attrs:
            target.attrs.remove(attr)
            names.append(attr.local_name)
            min_occurs.append(attr.restrictions.min_occurs)
            max_occurs.append(attr.restrictions.max_occurs)
            choices.append(self.build_attr_choice(attr))

        name = "choice" if len(names) > 3 else "_Or_".join(names)
        target.attrs.insert(
            pos,
            Attr(
                name=name,
                index=0,
                types=[AttrType(qname=str(DataType.ANY_TYPE), native=True)],
                tag=Tag.CHOICE,
                restrictions=Restrictions(
                    min_occurs=min((x for x in min_occurs if x is not None),
                                   default=0),
                    max_occurs=max((x for x in max_occurs if x is not None),
                                   default=0),
                ),
                choices=choices,
            ),
        )
    def create_substitution(cls, source: Class) -> Attr:
        """Create an attribute with type that refers to the given source class
        and namespaced qualified name."""

        return Attr(
            name=source.name,
            types=[AttrType(qname=source.qname)],
            tag=source.type.__name__,
            namespace=source.namespace,
        )
Exemple #7
0
    def get_or_create_attribute(cls, target: Class, name: str,
                                tag: str) -> Attr:
        """Find or create for the given parameters an attribute in the target
        class."""
        for attr in target.attrs:
            if attr.name == attr.local_name == name and attr.tag == tag:
                return attr

        attr = Attr(name=name, tag=tag)
        target.attrs.insert(0, attr)
        return attr
Exemple #8
0
    def get_or_create_attribute(cls, target: Class, name: str, tag: str) -> Attr:
        """Find or create for the given parameters an attribute in the target
        class."""
        for attr in target.attrs:
            if attr.name == name:
                return attr

        attr = Attr(name=name, tag=tag)
        attr.restrictions.min_occurs = 1
        attr.restrictions.max_occurs = 1
        target.attrs.insert(0, attr)
        return attr
Exemple #9
0
    def process(cls, target: Class):
        """Add an xs:anyType attribute to the given class if it supports mixed
        content and doesn't have a wildcard attribute yet."""

        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)
Exemple #10
0
 def build_attr(
     cls,
     name: str,
     qname: str,
     native: bool = False,
     forward: bool = False,
     namespace: Optional[str] = None,
     default: Optional[str] = None,
 ) -> Attr:
     """Builder method for attributes."""
     return Attr(
         tag=Tag.ELEMENT,
         name=name,
         namespace=namespace,
         default=default,
         types=[AttrType(qname=qname, forward=forward, native=native)],
     )
Exemple #11
0
    def create_substitution(cls, source: Class, qname: QName) -> Attr:
        """Create an attribute with type that refers to the given source class
        and namespaced qualified name."""
        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)],
            tag=source.type.__name__,
            namespace=source.namespace,
        )
Exemple #12
0
    def build_attribute(
        cls,
        target: Class,
        qname: str,
        attr_type: AttrType,
        target_namespace: Optional[str] = None,
        tag: str = Tag.ELEMENT,
        sequential: bool = False,
    ):

        namespace, name = split_qname(qname)
        namespace = cls.select_namespace(namespace, target_namespace, tag)
        index = len(target.attrs)

        attr = Attr(index=index, name=name, tag=tag, namespace=namespace)
        attr.types.append(attr_type)
        attr.restrictions.sequential = sequential or None
        cls.add_attribute(target, attr)
Exemple #13
0
 def build_attr(
     cls,
     name: str,
     qname: str,
     native: bool = False,
     forward: bool = False,
     namespace: Optional[str] = None,
     default: Optional[str] = None,
 ) -> Attr:
     """Builder method for attributes."""
     occurs = 1 if default is not None else None
     return Attr(
         tag=Tag.ELEMENT,
         name=name,
         namespace=namespace,
         default=default,
         types=[AttrType(qname=qname, forward=forward, native=native)],
         restrictions=Restrictions(min_occurs=occurs, max_occurs=occurs),
     )
Exemple #14
0
    def build_attr_choice(cls, attr: Attr) -> Attr:
        """
        Converts the given attr to a choice.

        The most important part is the reset of certain restrictions
        that don't make sense as choice metadata like occurrences.
        """
        restrictions = attr.restrictions.clone()
        restrictions.min_occurs = None
        restrictions.max_occurs = None
        restrictions.sequential = None

        return Attr(
            name=attr.local_name,
            namespace=attr.namespace,
            default=attr.default,
            types=attr.types,
            tag=attr.tag,
            help=attr.help,
            restrictions=restrictions,
        )
Exemple #15
0
    def group_fields(self, target: Class, attrs: List[Attr]):
        """Group attributes into a new compound field."""

        pos = target.attrs.index(attrs[0])
        choice = attrs[0].restrictions.choice
        sum_occurs = choice and choice.startswith("effective_")
        names = []
        choices = []
        min_occurs = []
        max_occurs = []
        for attr in attrs:
            target.attrs.remove(attr)
            names.append(attr.local_name)
            min_occurs.append(attr.restrictions.min_occurs or 0)
            max_occurs.append(attr.restrictions.max_occurs or 0)
            choices.append(self.build_attr_choice(attr))

        if len(names) > 3 or len(names) != len(set(names)):
            name = "choice"
        else:
            name = "_Or_".join(names)

        target.attrs.insert(
            pos,
            Attr(
                name=name,
                index=0,
                types=[AttrType(qname=str(DataType.ANY_TYPE), native=True)],
                tag=Tag.CHOICE,
                restrictions=Restrictions(
                    min_occurs=sum(min_occurs)
                    if sum_occurs else min(min_occurs),
                    max_occurs=sum(max_occurs)
                    if sum_occurs else max(max_occurs),
                ),
                choices=choices,
            ),
        )