Bases: RelativeHandlerInterface
Promote inner classes to root classes.
Source code in xsdata/codegen/handlers/unnest_inner_classes.py
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
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104 | class UnnestInnerClasses(RelativeHandlerInterface):
"""Promote inner classes to root classes."""
__slots__ = ()
def process(self, target: Class) -> None:
"""Promote all inner classes recursively.
Args:
target: The target class instance to process
"""
inner_classes = {}
inner_references = defaultdict(list)
promote_all = self.container.config.output.unnest_classes
for attr_type, source in self.find_forward_refs(target):
inner = ClassUtils.find_nested(source, attr_type.qname)
if not (promote_all or inner.is_enumeration):
continue
inner_classes[inner.ref] = inner
inner_references[inner.ref].append(attr_type)
for ref, inner in inner_classes.items():
references = inner_references[ref]
self.update_inner_class(inner)
self.update_types(references, inner)
self.container.add(inner)
self.remove_orphan_inner_classes(target, promote_all)
@classmethod
def remove_orphan_inner_classes(cls, target: Class, promote_all: bool):
"""Remove inner classes with no attr references.
Args:
target: The target class instance to process
promote_all: Whether to remove all inner classes or just the enumerations
"""
for inner in target.inner.copy():
if promote_all or inner.is_enumeration:
target.inner.remove(inner)
@classmethod
def find_forward_refs(cls, target: Class) -> Iterator[tuple[AttrType, Class]]:
"""Find all forward references for all inner classes.
Args:
target: The target class instance to process
Yields:
A tuple of attr type and the parent class instance.
"""
for attr in target.attrs:
for tp in attr.types:
if tp.forward and not tp.native:
yield tp, target
for inner in target.inner:
yield from cls.find_forward_refs(inner)
@classmethod
def update_inner_class(cls, target: Class):
"""Prepare the nested class to be added as root.
Args:
target: The target class
"""
assert target.parent is not None
name_parts = [target.parent.name, target.name]
new_qname = build_qname(target.target_namespace, "_".join(name_parts))
target.qname = new_qname
assert target.parent is not None
target.parent.inner.remove(target)
target.parent = None
target.local_type = True
@classmethod
def update_types(cls, types: list[AttrType], inner: Class):
"""Search and replace forward references.
Return the number changes.
Args:
types: The types to search and replace
inner: The updated inner class
"""
for tp in types:
tp.qname = inner.qname
tp.forward = False
tp.reference = inner.ref
|
process(target)
Promote all inner classes recursively.
Parameters:
Name | Type | Description | Default |
target | Class | The target class instance to process | required |
Source code in xsdata/codegen/handlers/unnest_inner_classes.py
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 | def process(self, target: Class) -> None:
"""Promote all inner classes recursively.
Args:
target: The target class instance to process
"""
inner_classes = {}
inner_references = defaultdict(list)
promote_all = self.container.config.output.unnest_classes
for attr_type, source in self.find_forward_refs(target):
inner = ClassUtils.find_nested(source, attr_type.qname)
if not (promote_all or inner.is_enumeration):
continue
inner_classes[inner.ref] = inner
inner_references[inner.ref].append(attr_type)
for ref, inner in inner_classes.items():
references = inner_references[ref]
self.update_inner_class(inner)
self.update_types(references, inner)
self.container.add(inner)
self.remove_orphan_inner_classes(target, promote_all)
|
remove_orphan_inner_classes(target, promote_all)
classmethod
Remove inner classes with no attr references.
Parameters:
Name | Type | Description | Default |
target | Class | The target class instance to process | required |
promote_all | bool | Whether to remove all inner classes or just the enumerations | required |
Source code in xsdata/codegen/handlers/unnest_inner_classes.py
42
43
44
45
46
47
48
49
50
51
52 | @classmethod
def remove_orphan_inner_classes(cls, target: Class, promote_all: bool):
"""Remove inner classes with no attr references.
Args:
target: The target class instance to process
promote_all: Whether to remove all inner classes or just the enumerations
"""
for inner in target.inner.copy():
if promote_all or inner.is_enumeration:
target.inner.remove(inner)
|
find_forward_refs(target)
classmethod
Find all forward references for all inner classes.
Parameters:
Name | Type | Description | Default |
target | Class | The target class instance to process | required |
Yields:
Type | Description |
tuple[AttrType, Class] | A tuple of attr type and the parent class instance. |
Source code in xsdata/codegen/handlers/unnest_inner_classes.py
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70 | @classmethod
def find_forward_refs(cls, target: Class) -> Iterator[tuple[AttrType, Class]]:
"""Find all forward references for all inner classes.
Args:
target: The target class instance to process
Yields:
A tuple of attr type and the parent class instance.
"""
for attr in target.attrs:
for tp in attr.types:
if tp.forward and not tp.native:
yield tp, target
for inner in target.inner:
yield from cls.find_forward_refs(inner)
|
update_inner_class(target)
classmethod
Prepare the nested class to be added as root.
Parameters:
Name | Type | Description | Default |
target | Class | | required |
Source code in xsdata/codegen/handlers/unnest_inner_classes.py
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89 | @classmethod
def update_inner_class(cls, target: Class):
"""Prepare the nested class to be added as root.
Args:
target: The target class
"""
assert target.parent is not None
name_parts = [target.parent.name, target.name]
new_qname = build_qname(target.target_namespace, "_".join(name_parts))
target.qname = new_qname
assert target.parent is not None
target.parent.inner.remove(target)
target.parent = None
target.local_type = True
|
update_types(types, inner)
classmethod
Search and replace forward references.
Return the number changes.
Parameters:
Name | Type | Description | Default |
types | list[AttrType] | The types to search and replace | required |
inner | Class | | required |
Source code in xsdata/codegen/handlers/unnest_inner_classes.py
91
92
93
94
95
96
97
98
99
100
101
102
103
104 | @classmethod
def update_types(cls, types: list[AttrType], inner: Class):
"""Search and replace forward references.
Return the number changes.
Args:
types: The types to search and replace
inner: The updated inner class
"""
for tp in types:
tp.qname = inner.qname
tp.forward = False
tp.reference = inner.ref
|