Skip to content

Commit

Permalink
Allow overriding compound fields
Browse files Browse the repository at this point in the history
  • Loading branch information
tefra committed Feb 25, 2023
1 parent c50188f commit 3f8af45
Show file tree
Hide file tree
Showing 2 changed files with 49 additions and 10 deletions.
40 changes: 34 additions & 6 deletions tests/codegen/handlers/test_create_compound_fields.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
from xsdata.codegen.models import Restrictions
from xsdata.models.config import GeneratorConfig
from xsdata.models.enums import DataType
from xsdata.models.enums import Tag
from xsdata.utils.testing import AttrFactory
from xsdata.utils.testing import AttrTypeFactory
from xsdata.utils.testing import ClassFactory
Expand Down Expand Up @@ -123,12 +124,6 @@ def test_choose_name(self):
actual = self.processor.choose_name(target, ["a", "b", "c", "d"])
self.assertEqual("choice_1", actual)

base = ClassFactory.create()
base.attrs.append(AttrFactory.create(name="Choice!"))
target.extensions.append(ExtensionFactory.reference(base.qname))
self.container.extend((target, base))

target.attrs.clear()
actual = self.processor.choose_name(target, ["a", "b", "c", "d"])
self.assertEqual("choice_1", actual)

Expand All @@ -140,6 +135,39 @@ def test_choose_name(self):
actual = self.processor.choose_name(target, ["a", "b", "c"])
self.assertEqual("ThisOrThat", actual)

def test_build_reserved_names(self):
base = ClassFactory.create(
attrs=[
AttrFactory.create("standalone"),
AttrFactory.create(
name="first",
tag=Tag.CHOICE,
choices=[
AttrFactory.create(name="a"),
AttrFactory.create(name="b"),
AttrFactory.create(name="c"),
],
),
AttrFactory.create(
name="second",
tag=Tag.CHOICE,
choices=[
AttrFactory.create(name="b"),
AttrFactory.create(name="c"),
],
),
]
)

target = ClassFactory.create()
target.extensions.append(ExtensionFactory.reference(qname=base.qname))
self.processor.container.extend([base, target])

actual = self.processor.build_reserved_names(target, names=["b", "c"])
expected = {"standalone", "first"}

self.assertEqual(expected, actual)

def test_build_attr_choice(self):
attr = AttrFactory.create(
name="a", namespace="xsdata", default="123", help="help", fixed=True
Expand Down
19 changes: 15 additions & 4 deletions xsdata/codegen/handlers/create_compound_fields.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
from collections import Counter
from collections import defaultdict
from typing import Dict
from typing import List
Expand All @@ -8,9 +9,9 @@
from xsdata.codegen.models import AttrType
from xsdata.codegen.models import Class
from xsdata.codegen.models import get_restriction_choice
from xsdata.codegen.models import get_slug
from xsdata.codegen.models import Restrictions
from xsdata.codegen.utils import ClassUtils
from xsdata.formats.dataclass.models.elements import XmlType
from xsdata.models.enums import DataType
from xsdata.models.enums import Tag
from xsdata.utils.collections import group_by
Expand Down Expand Up @@ -77,9 +78,6 @@ def group_fields(self, target: Class, attrs: List[Attr]):
)

def choose_name(self, target: Class, names: List[str]) -> str:
reserved = set(map(get_slug, self.base_attrs(target)))
reserved.update(map(get_slug, target.attrs))

if (
self.config.force_default_name
or len(names) > 3
Expand All @@ -89,8 +87,21 @@ def choose_name(self, target: Class, names: List[str]) -> str:
else:
name = "_Or_".join(names)

reserved = self.build_reserved_names(target, names)
return ClassUtils.unique_name(name, reserved)

def build_reserved_names(self, target: Class, names: List[str]) -> set[str]:
names_counter = Counter(names)
all_attrs = self.base_attrs(target)
all_attrs.extend(target.attrs)

return {
attr.slug
for attr in all_attrs
if attr.xml_type != XmlType.ELEMENTS
or Counter([x.local_name for x in attr.choices]) != names_counter
}

@classmethod
def build_attr_choice(cls, attr: Attr) -> Attr:
"""
Expand Down

0 comments on commit 3f8af45

Please sign in to comment.