예제 #1
0
    def unique_operations(self) -> Iterator[BindingOperation]:
        name_attr = operator.attrgetter("name")
        grouped_operations = collections.group_by(self.operations,
                                                  key=name_attr)

        for operations in grouped_operations.values():
            yield operations[-1]
예제 #2
0
    def group_compound_fields(self, target: Class):
        """Group and process target attributes by the choice group."""

        groups = group_by(target.attrs, lambda x: x.restrictions.choice)
        for choice, attrs in groups.items():
            if choice and len(attrs) > 1 and any(attr.is_list for attr in attrs):
                self.group_fields(target, attrs)
예제 #3
0
파일: sanitizer.py 프로젝트: gramm/xsdata
 def resolve_conflicts(self):
     """Find classes with the same case insensitive qualified name and
     rename them."""
     groups = group_by(self.container.iterate(), lambda x: alnum(x.qname))
     for classes in groups.values():
         if len(classes) > 1:
             self.rename_classes(classes)
예제 #4
0
파일: container.py 프로젝트: igieon/xsdata
    def filter_classes(self):
        """If there is any class derived from complexType or element then
        filter classes that should be generated, otherwise leave the container
        as it is."""

        candidates = list(filter(lambda x: x.should_generate, self.iterate()))
        if candidates:
            self.data = group_by(candidates, attrgetter("qname"))
예제 #5
0
파일: sanitizer.py 프로젝트: gramm/xsdata
 def process_duplicate_attribute_names(cls, attrs: List[Attr]) -> None:
     """Sanitize duplicate attribute names that might exist by applying
     rename strategies."""
     grouped = group_by(attrs, lambda attr: alnum(attr.name))
     for items in grouped.values():
         total = len(items)
         if total == 2 and not items[0].is_enumeration:
             cls.rename_attribute_by_preference(*items)
         elif total > 1:
             cls.rename_attributes_with_index(attrs, items)
예제 #6
0
파일: utils.py 프로젝트: neriusmika/xsdata
    def reduce(cls, classes: List[Class]) -> List[Class]:
        result = []
        indexed = collections.group_by(classes, key=lambda x: x.qname)
        for group in indexed.values():
            group.sort(key=lambda x: len(x.attrs))
            target = group.pop()

            for source in group:
                target.mixed = target.mixed or source.mixed
                cls.merge_attributes(target, source)

            result.append(target)

        return result
예제 #7
0
파일: validator.py 프로젝트: igieon/xsdata
    def handle_duplicate_types(cls, classes: List[Class]):
        """Handle classes with same namespace, name that are derived from the
        same xs type."""

        grouped = group_by(classes, lambda x: f"{x.type.__name__}{x.qname}")
        for items in grouped.values():
            if len(items) == 1:
                continue

            index = cls.select_winner(list(items))
            winner = items.pop(index)

            for item in items:
                classes.remove(item)

                if winner.container == Tag.REDEFINE:
                    cls.merge_redefined_type(item, winner)
예제 #8
0
파일: generator.py 프로젝트: igieon/xsdata
    def render_package(self, classes: List[Class]) -> str:
        """Render the source code for the __init__.py with all the imports of
        the generated class names."""

        imports = [
            Import(name=obj.name, source=obj.target_module)
            for obj in sorted(classes, key=lambda x: x.name)
        ]

        for group in group_by(imports, key=lambda x: x.name).values():
            if len(group) == 1:
                continue

            for index, cur in enumerate(group):
                cmp = group[index + 1] if index == 0 else group[index - 1]
                parts = re.split("[_.]", cur.source)
                diff = set(parts) - set(re.split("[_.]", cmp.source))

                add = "_".join(part for part in parts if part in diff)
                cur.alias = f"{add}:{cur.name}"

        return self.template("imports").render(imports=imports)
예제 #9
0
    def process_duplicate_attribute_names(cls, attrs: List[Attr]) -> None:
        """
        Sanitize duplicate attribute names that might exist by applying rename
        strategies.

        Steps:
            1. If more than two attributes share the same name or if they are
            enumerations append a numerical index to the attribute names.
            2. If one of the two fields has a specific namespace prepend it to the
            name. If possible rename the second field.
            3. Append the xml type to the name of one of the two attributes. if
            possible rename the second field or the field with xml type `attribute`.
        """
        grouped = group_by(attrs, lambda attr: attr.name.lower())
        for items in grouped.values():
            if len(items) == 1:
                continue

            if len(items) > 2 or items[0].is_enumeration:
                for index in range(1, len(items)):
                    num = 1
                    name = items[index].name.lower()

                    while any(attr for attr in attrs
                              if attr.name.lower() == f"{name}_{num}"):
                        num += 1

                    items[index].name = f"{name}_{num}"
            else:
                first, second = items
                if first.tag == second.tag and any(
                    (first.namespace, second.namespace)):
                    change = second if second.namespace else first
                    change.name = f"{text.clean_uri(change.namespace)}_{change.name}"
                else:
                    change = second if second.is_attribute else first
                    change.name = f"{change.name}_{change.tag}"
예제 #10
0
 def group_imports(cls, imports: List[Package]) -> Dict[str, List[Package]]:
     """Group the given list of packages by the source path."""
     return group_by(imports, lambda x: x.source)
예제 #11
0
 def from_list(cls, items: List[Class]) -> "ClassContainer":
     """Static constructor from a list of classes."""
     return cls(group_by(items, attrgetter("qname")))
예제 #12
0
파일: container.py 프로젝트: rmr1154/xsdata
 def from_list(cls, items: List[Class]) -> "ClassContainer":
     """Static constructor from a list of classes."""
     return cls(group_by(items, methodcaller("source_qname")))
예제 #13
0
output = [
    ".. list-table::",
    "    :widths: auto",
    "    :header-rows: 1",
    "    :align: left",
    "",
    "    * - Python",
    "      - XML Type",
    "      -",
    "      -",
    "      -",
    "      -",
]

groups = group_by(list(DataType), key=lambda x: x.type.__name__.lower())
for key in sorted(groups):
    tp = groups[key][0].type
    if tp.__module__ != "builtins":
        output.append(f"    * - :class:`~{tp.__module__}.{tp.__name__}`")
    else:
        output.append(f"    * - :class:`{tp.__name__}`")

    count = 0
    for dt in groups[key]:
        output.append(f"      - {dt.code}")
        count += 1
        if count == 5:
            output.append("    * -")
            count = 0
예제 #14
0
파일: mixins.py 프로젝트: neriusmika/xsdata
 def group_by_module(cls, classes: List[Class]) -> Dict[Path, List[Class]]:
     """Group the given list of classes by the target module directory."""
     return group_by(classes, lambda x: module_path(x.target_module))
예제 #15
0
    "    :align: left",
    "",
    "    * - Python",
    "      - XML Type",
    "      -",
    "      -",
    "      -",
    "      -",
]

custom_classes = {
    "Decimal": "decimal.Decimal",
    "QName": "xml.etree.ElementTree.QName",
}

for tp, data_types in group_by(list(DataType),
                               key=lambda x: x.type.__name__).items():
    output.append(f"    * - :class:`{custom_classes.get(tp, tp)}`")

    count = 0
    for dt in data_types:
        output.append(f"      - {dt.code}")
        count += 1
        if count == 5:
            output.append("    * -")
            count = 0

    output.extend(["      -" for _ in range(5 - count)])

output.append("    * - :class:`enum.Enum`")
output.append("      - enumeration")
output.append("      -")