Exemple #1
0
    def test_build_message_class(self, mock_create_message_attributes):
        message = Message(name="bar", parts=[Part()])
        message.ns_map["foo"] = "bar"
        definitions = Definitions(
            messages=[message], target_namespace="xsdata", location="foo.wsdl"
        )
        port_type_message = PortTypeMessage(message="foo:bar")

        attrs = AttrFactory.list(2)
        mock_create_message_attributes.return_value = attrs
        actual = DefinitionsMapper.build_message_class(definitions, port_type_message)
        expected = Class(
            qname=build_qname("xsdata", "bar"),
            status=Status.PROCESSED,
            type=Element,
            module="foo",
            ns_map=message.ns_map,
            attrs=attrs,
        )
        self.assertEqual(expected, actual)
Exemple #2
0
    def map_binding_operation(
        cls,
        definitions: Definitions,
        binding_operation: BindingOperation,
        port_type_operation: PortTypeOperation,
        config: Dict,
        name: str,
    ) -> Iterator[Class]:
        """Step 4: Convert a BindingOperation to a service class and delegate
        the process of all the message classes to the next entry point."""

        attrs = [
            cls.build_attr(key,
                           str(DataType.STRING),
                           native=True,
                           default=config[key])
            for key in sorted(config.keys(), key=len) if config[key]
        ]

        style = config.get("style", "document")
        name = f"{name}_{binding_operation.name}"
        namespace = cls.operation_namespace(config)
        operation_messages = cls.map_binding_operation_messages(
            definitions, binding_operation, port_type_operation, name, style,
            namespace)
        for message_class in operation_messages:
            yield message_class
            # Only Envelope classes need to be added in service input/output
            if message_class.meta_name:
                message_type = message_class.name.split("_")[-1]
                attrs.append(cls.build_attr(message_type, message_class.qname))

        yield Class(
            qname=build_qname(definitions.target_namespace, name),
            status=Status.PROCESSED,
            tag=type(binding_operation).__name__,
            module=definitions.module,
            ns_map=binding_operation.ns_map,
            attrs=attrs,
        )
Exemple #3
0
    def promote_inner_class(self, parent: Class, inner: Class):
        """
        Convert inner class to root class.

        Steps:
            1. Remove inner class from parent
            2. Prepend parent name to inner class name.
            3. Search and replace all matching attribute types.
            4. Add inner class to the global class index.
        """
        name = f"{parent.name}_{inner.name}"
        parent.inner.remove(inner)

        for attr in parent.attrs:
            for attr_type in attr.types:
                if attr_type.name == inner.name:
                    attr_type.forward = False
                    attr_type.qname = QName(inner.qname.namespace, name)

        inner.qname = QName(inner.qname.namespace, name)

        self.container.add(inner)
Exemple #4
0
    def build_class(self, obj: ElementBase, container: Optional[str] = None) -> Class:
        """Build and return a class instance."""
        name = obj.real_name
        namespace = self.element_namespace(obj)
        instance = Class(
            name=name,
            abstract=obj.is_abstract,
            namespace=namespace,
            mixed=obj.is_mixed,
            nillable=obj.is_nillable,
            type=type(obj),
            container=container,
            help=obj.display_help,
            ns_map=obj.ns_map,
            source_namespace=self.schema.target_namespace,
            module=self.schema.module,
            substitutions=obj.substitutions,
        )

        self.build_class_extensions(obj, instance)
        self.build_class_attributes(obj, instance)
        return instance
Exemple #5
0
    def process_attribute(self, target: Class, attr: Attr):
        """
        Check if the given attribute matches any substitution class in order to
        clone it's attributes to the target class.

        The cloned attributes are placed below the attribute the are
        supposed to substitute.
        """
        index = target.attrs.index(attr)
        qname = target.source_qname(attr.name)

        assert self.substitutions is not None

        for substitution in self.substitutions.get(qname, []):
            pos = collections.find(target.attrs, substitution)
            index = pos + 1 if pos > -1 else index

            clone = substitution.clone()
            clone.restrictions.merge(attr.restrictions)
            target.attrs.insert(index, clone)

            self.process_attribute(target, clone)
Exemple #6
0
    def process(cls, target: Class):
        """Process classes that contain attributes derived from xs:enumeration
        and any other xs element."""

        if target.is_enumeration or not any(attr.is_enumeration
                                            for attr in target.attrs):
            return

        enumerations = []
        for attr in list(target.attrs):
            if attr.is_enumeration:
                target.attrs.remove(attr)
                enumerations.append(attr)

        if len(target.attrs) > 1:
            raise AnalyzerValueError(
                "Mixed enumeration with more than one normal field.")

        enum_inner = next(
            (inner for inner in target.inner if inner.is_enumeration), None)
        if not enum_inner:
            enum_inner = Class(
                qname=QName(target.qname.namespace, "value"),
                type=SimpleType,
                module=target.module,
                package=target.package,
                mixed=False,
                abstract=False,
                nillable=False,
            )
            target.attrs[0].types.append(
                AttrType(
                    qname=QName(target.qname.namespace, "value"),
                    forward=True,
                ))
            target.inner.append(enum_inner)

        enum_inner.attrs.extend(enumerations)
Exemple #7
0
    def build_envelope_class(
        cls,
        definitions: Definitions,
        binding_message: BindingMessage,
        port_type_message: PortTypeMessage,
        name: str,
        style: str,
        namespace: Optional[str],
    ) -> Class:
        """Step 6.1: Build Envelope class for the given binding message with
        attributes from the port type message."""

        target = Class(
            qname=build_qname(definitions.target_namespace, name),
            meta_name="Envelope",
            type=type(binding_message),
            module=definitions.module,
            ns_map=binding_message.ns_map,
            namespace=namespace,
        )
        message = port_type_message.message

        for ext in binding_message.extended_elements:
            assert ext.qname is not None
            local_name = split_qname(ext.qname)[1].title()
            inner = cls.build_inner_class(target, local_name)

            if style == "rpc" and local_name == "Body":
                namespace = ext.attributes.get("namespace")
                attrs = cls.map_port_type_message(port_type_message, namespace)
            else:
                attrs = cls.map_binding_message_parts(
                    definitions, message, ext, inner.ns_map
                )

            inner.attrs.extend(attrs)

        return target
Exemple #8
0
    def build_inner_class(
        cls, target: Class, name: str, namespace: Optional[str] = None
    ) -> Class:
        """
        Build or retrieve an inner class for the given target class by the
        given name.

        This helper will also create a forward reference attribute for
        the parent class.
        """
        inner = first(inner for inner in target.inner if inner.name == name)
        if not inner:
            inner = Class(
                qname=build_qname(name),
                type=BindingMessage,
                module=target.module,
                ns_map=target.ns_map.copy(),
            )
            attr = cls.build_attr(name, inner.qname, forward=True, namespace=namespace)

            target.inner.append(inner)
            target.attrs.append(attr)

        return inner
Exemple #9
0
 def process_class(x: Class):
     x.status = Status.PROCESSED
Exemple #10
0
 def process_class(x: Class):
     x.status = Status.PROCESSED
     if x is first:
         first.attrs.clear()
Exemple #11
0
 def add(self, item: Class):
     """Add class item to the container."""
     self.data.setdefault(item.source_qname(), []).append(item)
Exemple #12
0
    def test_build_envelope_class_with_style_rpc(
        self,
        mock_get_or_create_inner_class,
        mock_map_binding_message_parts,
        mock_map_port_type_message,
    ):
        mock_get_or_create_inner_class.side_effect = mock_create_inner
        mock_map_binding_message_parts.side_effect = mock_create_attr
        mock_map_port_type_message.side_effect = mock_create_attr

        name = "some_operation_bindings"
        style = "rpc"
        namespace = "xsdata"
        definitions = Definitions(location="foo.wsdl", target_namespace="bar")
        port_type_message = PortTypeMessage(message="some_operation")
        binding_message = BindingMessage(extended=[
            AnyElement(qname="body", attributes={"namespace": "bodyns"}),
            AnyElement(qname="header"),
            AnyElement(qname="header"),
        ])
        binding_message.ns_map["foo"] = "bar"

        result = DefinitionsMapper.build_envelope_class(
            definitions, binding_message, port_type_message, name, style,
            namespace)

        expected = Class(
            qname=build_qname("bar", name),
            meta_name="Envelope",
            tag=Tag.BINDING_MESSAGE,
            module="foo",
            ns_map={"foo": "bar"},
            namespace="xsdata",
        )
        self.assertEqual(2, len(result.inner))
        self.assertEqual(1, len(result.inner[0].attrs))
        self.assertEqual(2, len(result.inner[1].attrs))
        self.maxDiff = None
        mock_map_port_type_message.assert_called_once_with(
            port_type_message, "bodyns")

        mock_map_binding_message_parts.assert_has_calls([
            mock.call(
                definitions,
                port_type_message.message,
                binding_message.extended[1],
                result.inner[1].ns_map,
            ),
            mock.call(
                definitions,
                port_type_message.message,
                binding_message.extended[2],
                result.inner[1].ns_map,
            ),
        ])
        mock_get_or_create_inner_class.assert_has_calls([
            mock.call(mock.ANY, "Body"),
            mock.call(mock.ANY, "Header"),
            mock.call(mock.ANY, "Header"),
        ])

        result.inner.clear()
        self.assertEqual(expected, result)
Exemple #13
0
    def process(cls, target: Class):
        """Drop non enum attributes from enum classes."""

        enumerations = [attr for attr in target.attrs if attr.is_enumeration]
        if enumerations:
            target.attrs = enumerations
 def clone_enumeration(cls, inner: Class, name: str) -> Class:
     clone = inner.clone()
     clone.qname = build_qname(clone.target_namespace,
                               f"{name}_{clone.name}")
     return clone
 def filter(cls, target: Class):
     """Filter attrs not derived from xs:enumeration if there are any
     xs:enumeration attrs."""
     enumerations = [attr for attr in target.attrs if attr.is_enumeration]
     if enumerations:
         target.attrs = enumerations
Exemple #16
0
    def test_build_envelope_class(
        self,
        mock_get_or_create_inner_class,
        mock_map_binding_message_parts,
        mock_map_port_type_message,
    ):
        mock_get_or_create_inner_class.side_effect = mock_create_inner
        mock_map_binding_message_parts.side_effect = mock_create_attr

        name = "some_operation_bindings"
        style = "document"
        namespace = "xsdata"
        definitions = Definitions(location="foo.wsdl", target_namespace="bar")
        port_type_message = PortTypeMessage(message="some_operation")
        binding_message = BindingMessage(
            extended=[
                AnyElement(qname="body"),
                AnyElement(qname="header"),
                AnyElement(qname="header"),
            ]
        )
        binding_message.ns_map["foo"] = "bar"

        result = DefinitionsMapper.build_envelope_class(
            definitions, binding_message, port_type_message, name, style, namespace
        )

        expected = Class(
            qname=build_qname("bar", name),
            meta_name="Envelope",
            type=BindingMessage,
            module="foo",
            ns_map={"foo": "bar"},
            namespace="xsdata",
        )
        self.assertEqual(2, len(result.inner))
        self.assertEqual(1, len(result.inner[0].attrs))
        self.assertEqual(2, len(result.inner[1].attrs))
        self.assertEqual(0, mock_map_port_type_message.call_count)
        mock_map_binding_message_parts.assert_has_calls(
            [
                mock.call(
                    definitions,
                    port_type_message.message,
                    binding_message.extended[0],
                    result.inner[0].ns_map,
                ),
                mock.call(
                    definitions,
                    port_type_message.message,
                    binding_message.extended[1],
                    result.inner[1].ns_map,
                ),
                mock.call(
                    definitions,
                    port_type_message.message,
                    binding_message.extended[2],
                    result.inner[1].ns_map,
                ),
            ]
        )
        mock_get_or_create_inner_class.assert_has_calls(
            [
                mock.call(mock.ANY, "Body"),
                mock.call(mock.ANY, "Header"),
                mock.call(mock.ANY, "Header"),
            ]
        )

        result.inner.clear()
        self.assertEqual(expected, result)