File: unnest_inner_classes.py

package info (click to toggle)
python-xsdata 24.1-2
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 2,936 kB
  • sloc: python: 29,257; xml: 404; makefile: 27; sh: 6
file content (54 lines) | stat: -rw-r--r-- 1,784 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
from typing import Optional

from xsdata.codegen.mixins import RelativeHandlerInterface
from xsdata.codegen.models import Attr, Class
from xsdata.utils.namespaces import build_qname


class UnnestInnerClasses(RelativeHandlerInterface):
    """Unnest class processor."""

    __slots__ = ()

    def process(self, target: Class):
        """
        Promote enumeration classes to root classes.

        Candidates
            - Enumerations
            - All if config is enabled
        """
        for inner in list(target.inner):
            if inner.is_enumeration or self.container.config.output.unnest_classes:
                self.promote(target, inner)

    def promote(self, target: Class, inner: Class):
        target.inner.remove(inner)
        attr = self.find_forward_attr(target, inner.qname)
        if attr:
            clone = self.clone_class(inner, target.name)
            self.update_types(attr, inner.qname, clone.qname)
            self.container.add(clone)

    @classmethod
    def clone_class(cls, inner: Class, name: str) -> Class:
        clone = inner.clone()
        clone.local_type = True
        clone.qname = build_qname(inner.target_namespace, f"{name}_{inner.name}")
        return clone

    @classmethod
    def update_types(cls, attr: Attr, search: str, replace: str):
        for attr_type in attr.types:
            if attr_type.qname == search and attr_type.forward:
                attr_type.qname = replace
                attr_type.forward = False

    @classmethod
    def find_forward_attr(cls, target: Class, qname: str) -> Optional[Attr]:
        for attr in target.attrs:
            for attr_type in attr.types:
                if attr_type.forward and attr_type.qname == qname:
                    return attr

        return None