예제 #1
0
    def test_process_class(
        self,
        mock_process_attribute_default,
        mock_process_attribute_restrictions,
        mock_process_attribute_sequence,
        mock_process_duplicate_attribute_names,
    ):
        target = ClassFactory.elements(2)
        inner = ClassFactory.elements(1)
        target.inner.append(inner)

        self.sanitizer.process_class(target)

        calls_with_target = [
            mock.call(target.inner[0], target.inner[0].attrs[0]),
            mock.call(target, target.attrs[0]),
            mock.call(target, target.attrs[1]),
        ]

        calls_without_target = [
            mock.call(target.inner[0].attrs[0]),
            mock.call(target.attrs[0]),
            mock.call(target.attrs[1]),
        ]

        mock_process_attribute_default.assert_has_calls(calls_with_target)
        mock_process_attribute_restrictions.assert_has_calls(
            calls_without_target)
        mock_process_attribute_sequence.assert_has_calls(calls_with_target)
        mock_process_duplicate_attribute_names.assert_has_calls(
            [mock.call(target.inner[0].attrs),
             mock.call(target.attrs)])
예제 #2
0
    def test_copy_attribute_properties_from_nillable_source(self):
        source = ClassFactory.elements(1, nillable=True)
        target = ClassFactory.elements(1)
        attr = target.attrs[0]

        self.processor.copy_attribute_properties(source, target, attr, attr.types[0])
        self.assertTrue(attr.restrictions.nillable)
예제 #3
0
    def test_render(self):
        classes = [
            ClassFactory.elements(2, package="foo"),
            ClassFactory.elements(3, package="foo"),
        ]

        iterator = self.generator.render(classes)

        actual = [(out.path, out.title, out.source) for out in iterator]
        self.assertEqual(1, len(actual))
        self.assertEqual(3, len(actual[0]))
        self.assertIsInstance(actual[0][0], Path)
        self.assertTrue(actual[0][0].is_absolute())
        self.assertEqual("foo.tests", actual[0][1])
        self.assertEqual(
            str(Path("foo/tests.pu")), str(actual[0][0].relative_to(Path.cwd()))
        )

        output = (
            "@startuml\n"
            "\n"
            "class class_B {\n"
            "    +attr_B : string\n"
            "    +attr_C : string\n"
            "}\n"
            "class class_C {\n"
            "    +attr_D : string\n"
            "    +attr_E : string\n"
            "    +attr_F : string\n"
            "}\n"
            "\n"
            "@enduml"
            "\n"
        )
        self.assertEqual(output, actual[0][2])
예제 #4
0
    def test_copy_attribute_properties(self, mock_copy_inner_class):
        source = ClassFactory.elements(1, qname="Foobar")
        source.attrs[0].restrictions.max_length = 100
        source.attrs[0].restrictions.min_length = 1
        source.attrs[0].help = "foo"
        source.attrs[0].types = [
            AttrTypeFactory.create(qname="first"),
            AttrTypeFactory.create(qname="second"),
        ]

        target = ClassFactory.elements(1)
        attr = target.attrs[0]
        attr.restrictions.min_length = 2
        attr.types.clear()
        attr.types.append(AttrTypeFactory.create(qname=source.name))

        self.assertEqual("Foobar", attr.types[0].name)
        self.processor.copy_attribute_properties(source, target, attr,
                                                 attr.types[0])

        self.assertEqual("first", attr.types[0].name)
        self.assertEqual("second", attr.types[1].name)
        self.assertEqual("foo", attr.help)
        self.assertEqual(Restrictions(min_length=2, max_length=100),
                         attr.restrictions)
        mock_copy_inner_class.assert_has_calls([
            mock.call(source, target, attr, source.attrs[0].types[0]),
            mock.call(source, target, attr, source.attrs[0].types[1]),
        ])
예제 #5
0
    def test_copy_group_attributes(self, mock_clone_attribute, mock_copy_inner_classes):
        mock_clone_attribute.side_effect = lambda x, y: x.clone()
        source = ClassFactory.elements(2)
        source.inner.append(ClassFactory.create())
        target = ClassFactory.elements(3)
        attrs = list(target.attrs)
        attrs[1].name = "bar"

        ClassUtils.copy_group_attributes(source, target, target.attrs[1])

        self.assertEqual(4, len(target.attrs))
        self.assertEqual(source.attrs[0], target.attrs[1])
        self.assertEqual(source.attrs[1], target.attrs[2])
        mock_copy_inner_classes.assert_has_calls(
            [
                mock.call(source, target, source.attrs[0]),
                mock.call(source, target, source.attrs[1]),
            ]
        )
        mock_clone_attribute.assert_has_calls(
            [
                mock.call(source.attrs[0], attrs[1].restrictions),
                mock.call(source.attrs[1], attrs[1].restrictions),
            ]
        )
예제 #6
0
    def test_process_simple_extension_when_source_and_target_are_not_enumerations(
            self, mock_copy_attributes):
        source = ClassFactory.elements(2)
        target = ClassFactory.elements(1)
        extension = ExtensionFactory.create()

        self.processor.process_simple_extension(source, target, extension)
        mock_copy_attributes.assert_called_once_with(source, target, extension)
예제 #7
0
    def test_should_flatten_extension(self):
        source = ClassFactory.create()
        target = ClassFactory.create()

        self.assertFalse(self.processor.should_flatten_extension(source, target))

        # Source has suffix attr and target has its own attrs
        source = ClassFactory.elements(1)
        source.attrs[0].index = sys.maxsize
        target.attrs.append(AttrFactory.create())
        self.assertTrue(self.processor.should_flatten_extension(source, target))

        # Target has suffix attr
        source = ClassFactory.create()
        target = ClassFactory.elements(1)
        target.attrs[0].index = sys.maxsize
        self.assertTrue(self.processor.should_flatten_extension(source, target))

        # Source is a simple type
        source = ClassFactory.create(attrs=[AttrFactory.create(tag=Tag.SIMPLE_TYPE)])
        target = ClassFactory.elements(1)
        self.assertTrue(self.processor.should_flatten_extension(source, target))

        # Sequential violation
        source = ClassFactory.elements(3)
        target = source.clone()
        self.assertFalse(self.processor.should_flatten_extension(source, target))

        for attr in target.attrs:
            attr.restrictions.sequential = True

        self.assertFalse(self.processor.should_flatten_extension(source, target))

        target.attrs = [target.attrs[1], target.attrs[0], target.attrs[2]]
        self.assertTrue(self.processor.should_flatten_extension(source, target))

        # Types violation
        target = source.clone()
        target.attrs[1].types = [
            AttrTypeFactory.native(DataType.INT),
            AttrTypeFactory.native(DataType.FLOAT),
        ]

        source.attrs[1].types = [
            AttrTypeFactory.native(DataType.INT),
            AttrTypeFactory.native(DataType.FLOAT),
            AttrTypeFactory.native(DataType.DECIMAL),
        ]
        self.assertFalse(self.processor.should_flatten_extension(source, target))
        target.attrs[1].types.append(AttrTypeFactory.native(DataType.QNAME))
        self.assertTrue(self.processor.should_flatten_extension(source, target))
예제 #8
0
    def test_process_complex_extension_removes_extension(
            self, mock_should_remove_extension, mock_copy_attributes):
        mock_should_remove_extension.return_value = True
        extension = ExtensionFactory.create()
        target = ClassFactory.elements(1, extensions=[extension])
        source = ClassFactory.elements(5)

        self.processor.process_complex_extension(source, target, extension)

        self.assertEqual(0, len(target.extensions))
        self.assertEqual(1, len(target.attrs))

        mock_should_remove_extension.assert_called_once_with(source, target)
        self.assertEqual(0, mock_copy_attributes.call_count)
예제 #9
0
    def test_remove_inherited_fields_with_lists_type(self):
        target = ClassFactory.elements(2)
        target.attrs[0].restrictions.min_occurs = 1
        target.attrs[0].restrictions.max_occurs = 3

        source = target.clone()
        source.qname = "BaseClass"
        target.attrs[0].restrictions.min_occurs = 0
        target.attrs[1].restrictions.max_occurs = 10

        target.extensions.append(ExtensionFactory.reference(source.qname))
        self.processor.container.add(source)

        self.processor.process(target)
        self.assertEqual(2, len(target.attrs))  # min/max occurs didn't match

        self.processor.container.config.output.compound_fields = True
        self.processor.process(target)
        self.assertEqual(2, len(
            target.attrs))  # The are not part of a choice group

        target.attrs[0].restrictions.choice = "123"
        target.attrs[1].restrictions.choice = "123"
        source.attrs[0].restrictions.choice = "456"
        source.attrs[1].restrictions.choice = "456"
        self.processor.process(target)
        self.assertEqual(0, len(target.attrs))
예제 #10
0
    def test_add_default_attribute(self):
        xs_string = AttrTypeFactory.native(DataType.STRING)
        extension = ExtensionFactory.create(xs_string,
                                            Restrictions(required=True))
        item = ClassFactory.elements(1, extensions=[extension])

        ClassExtensionHandler.add_default_attribute(item, extension)
        expected = AttrFactory.create(name="@value",
                                      default=None,
                                      types=[xs_string],
                                      tag=Tag.EXTENSION)

        self.assertEqual(2, len(item.attrs))
        self.assertEqual(0, len(item.extensions))
        self.assertEqual(expected, item.attrs[0])

        xs_int = AttrTypeFactory.native(DataType.INT)
        extension = ExtensionFactory.create(xs_int, Restrictions(tokens=True))
        item.extensions.append(extension)
        ClassExtensionHandler.add_default_attribute(item, extension)

        expected.types.append(xs_int)
        expected_restrictions = Restrictions(tokens=True,
                                             required=True,
                                             min_occurs=1,
                                             max_occurs=1)

        self.assertEqual(2, len(item.attrs))
        self.assertEqual(0, len(item.extensions))
        self.assertEqual(expected, item.attrs[0])
        self.assertEqual(expected_restrictions, item.attrs[0].restrictions)
예제 #11
0
    def test_render_module(self):
        classes = [
            ClassFactory.enumeration(2, help="\n\nI am enum  "),
            ClassFactory.elements(2),
            ClassFactory.service(2),
        ]
        classes[0].attrs[0].help = "I am a member"
        classes[1].attrs[0].help = "I am a field"

        resolver = DependenciesResolver()

        actual = self.generator.render_module(resolver, classes)
        expected = ("from dataclasses import dataclass, field\n"
                    "from enum import Enum\n"
                    "from typing import Optional\n"
                    "\n"
                    '__NAMESPACE__ = "xsdata"\n'
                    "\n"
                    "\n"
                    "class ClassB(Enum):\n"
                    '    """\n'
                    "    I am enum.\n"
                    "\n"
                    "    :cvar ATTR_B: I am a member\n"
                    "    :cvar ATTR_C:\n"
                    '    """\n'
                    "    ATTR_B = None\n"
                    "    ATTR_C = None\n"
                    "\n"
                    "\n"
                    "@dataclass\n"
                    "class ClassC:\n"
                    '    """\n'
                    "    :ivar attr_d: I am a field\n"
                    "    :ivar attr_e:\n"
                    '    """\n'
                    "    class Meta:\n"
                    '        name = "class_C"\n'
                    "\n"
                    "    attr_d: Optional[str] = field(\n"
                    "        default=None,\n"
                    "        metadata={\n"
                    '            "name": "attr_D",\n'
                    '            "type": "Element",\n'
                    "        }\n"
                    "    )\n"
                    "    attr_e: Optional[str] = field(\n"
                    "        default=None,\n"
                    "        metadata={\n"
                    '            "name": "attr_E",\n'
                    '            "type": "Element",\n'
                    "        }\n"
                    "    )\n"
                    "\n"
                    "\n"
                    "class ClassD:\n"
                    '    attr_f = "None"\n'
                    '    attr_g = "None"\n')

        self.assertEqual(expected, actual)
예제 #12
0
    def test_process(self):
        item = ClassFactory.create()
        self.processor.process(item)
        self.assertEqual(0, len(item.attrs))

        item = ClassFactory.elements(2, mixed=True)
        self.processor.process(item)
        expected = AttrFactory.create(
            name="content",
            types=[AttrTypeFactory.native(DataType.ANY_TYPE)],
            tag=Tag.ANY,
            namespace="##any",
        )

        # Wildcard is not defined
        self.assertEqual(expected, item.attrs[0])
        self.assertTrue(item.attrs[0].is_list)
        self.assertEqual(3, len(item.attrs))
        self.assertTrue(item.attrs[0].mixed)

        # Wildcard is defined and is list
        item.attrs[0].restrictions.max_occurs = 3
        item.attrs[0].mixed = False
        self.processor.process(item)
        self.assertEqual(3, len(item.attrs))
        self.assertTrue(item.attrs[0].mixed)
        self.assertEqual(3, item.attrs[0].restrictions.max_occurs)

        # Wildcard is defined but not list
        item.attrs[0].restrictions.max_occurs = 1
        self.processor.process(item)
        self.assertTrue(item.attrs[0].is_list)
        self.assertEqual(sys.maxsize, item.attrs[0].restrictions.max_occurs)
예제 #13
0
    def test_promote(self):
        target = ClassFactory.elements(2)
        inner = ClassFactory.enumeration(3)

        target.inner.append(inner)
        target.inner.append(ClassFactory.simple_type())  # Irrelevant
        attr_type = AttrTypeFactory.create(qname=inner.qname, forward=True)

        target.attrs[0].types.append(attr_type.clone())
        target.attrs[1].types.append(attr_type.clone())

        self.container.add(target)
        self.assertEqual(3, len(self.container.data))

        self.processor.process(target)

        new_qname = build_qname(inner.target_namespace,
                                f"{target.name}_{inner.name}")

        self.assertEqual(4, len(self.container.data))
        new_inner = self.container.find(new_qname)

        self.assertEqual(1, len(target.inner))
        self.assertNotEqual(new_inner.qname, inner.qname)
        self.assertEqual(new_inner.attrs, inner.attrs)
        self.assertEqual(new_inner.qname, target.attrs[0].types[1].qname)
        self.assertEqual(new_inner.qname, target.attrs[1].types[1].qname)
        self.assertFalse(target.attrs[0].types[1].forward)
        self.assertFalse(target.attrs[1].types[1].forward)
예제 #14
0
    def test_process_simple_extension_when_source_is_enumeration_and_target_is_not(
            self, mock_add_default_attribute):
        source = ClassFactory.enumeration(2)
        target = ClassFactory.elements(1)
        extension = ExtensionFactory.create()

        self.processor.process_simple_extension(source, target, extension)
        mock_add_default_attribute.assert_called_once_with(target, extension)
예제 #15
0
    def test_process_extension_with_native_type(self,
                                                mock_flatten_extension_native):
        extension = ExtensionFactory.native(DataType.STRING)
        target = ClassFactory.elements(1, extensions=[extension])

        self.processor.process_extension(target, extension)
        mock_flatten_extension_native.assert_called_once_with(
            target, extension)
예제 #16
0
    def test_process_extension_with_dependency_type(
            self, mock_process_dependency_extension):
        extension = ExtensionFactory.create(AttrTypeFactory.create("foo"))
        target = ClassFactory.elements(1, extensions=[extension])

        self.processor.process_extension(target, extension)
        mock_process_dependency_extension.assert_called_once_with(
            target, extension)
예제 #17
0
    def test_validate_references(self):
        first = ClassFactory.elements(2)
        second = ClassFactory.create(attrs=first.attrs)

        ClassAnalyzer.validate_references([first])

        with self.assertRaises(AnalyzerValueError) as cm:
            ClassAnalyzer.validate_references([first, second])

        self.assertEqual("Cross references detected!", str(cm.exception))
예제 #18
0
    def test_process_enum_extension_raises_exception(self):
        source = ClassFactory.elements(2)
        target = ClassFactory.enumeration(2)
        extension = ExtensionFactory.reference(source.qname)
        target.extensions.append(extension)
        self.processor.container.add(source)
        self.processor.container.add(target)

        with self.assertRaises(CodeGenerationError):
            self.processor.process_dependency_extension(target, extension)
예제 #19
0
    def test_filter(self):
        target = ClassFactory.elements(2)
        self.processor.process(target)

        self.assertEqual(2, len(target.attrs))

        target.attrs.append(AttrFactory.enumeration())
        self.processor.process(target)
        self.assertEqual(1, len(target.attrs))
        self.assertTrue(target.attrs[0].is_enumeration)
예제 #20
0
    def test_process_simple_extension_when_target_is_enumeration_and_source_is_not(
            self, mock_add_default_attribute, mock_copy_attributes):
        extension = ExtensionFactory.create()
        source = ClassFactory.elements(2)
        target = ClassFactory.enumeration(1, extensions=[extension])

        self.processor.process_simple_extension(source, target, extension)
        self.assertEqual(0, mock_add_default_attribute.call_count)
        self.assertEqual(0, mock_copy_attributes.call_count)
        self.assertEqual(0, len(target.extensions))
예제 #21
0
    def test_process_inner_type_with_complex_type(
            self, mock_copy_attribute_properties, mock_update_restrictions):
        target = ClassFactory.create()
        inner = ClassFactory.elements(2, qname="a", status=Status.PROCESSED)
        attr = AttrFactory.create(types=[AttrTypeFactory.create(qname="a")])

        target.inner.append(inner)
        self.processor.process_inner_type(target, attr, attr.types[0])
        self.assertIn(inner, target.inner)
        self.assertEqual(0, mock_copy_attribute_properties.call_count)
        self.assertEqual(0, mock_update_restrictions.call_count)
예제 #22
0
    def test_replace_attributes_type(self):
        extension = ExtensionFactory.create()
        target = ClassFactory.elements(2)
        target.extensions.append(extension)

        ClassExtensionHandler.replace_attributes_type(target, extension)

        self.assertEqual(1, len(target.attrs[0].types))
        self.assertEqual(1, len(target.attrs[1].types))
        self.assertEqual(extension.type, target.attrs[0].types[0])
        self.assertEqual(extension.type, target.attrs[1].types[0])
        self.assertEqual(0, len(target.extensions))
예제 #23
0
    def test_create_substitution(self):
        item = ClassFactory.elements(1, qname=build_qname("foo", "bar"))
        actual = self.processor.create_substitution(item)

        expected = AttrFactory.create(
            name=item.name,
            default=None,
            types=[AttrType(qname=build_qname("foo", "bar"))],
            tag=item.tag,
        )

        self.assertEqual(expected, actual)
예제 #24
0
    def test_process_dependency_type_with_complex_type(
        self, mock_find_dependency, mock_set_circular_flag
    ):
        complex_type = ClassFactory.elements(1)
        mock_find_dependency.return_value = complex_type

        target = ClassFactory.create()
        attr = AttrFactory.create()
        attr_type = attr.types[0]

        self.processor.process_dependency_type(target, attr, attr_type)
        mock_set_circular_flag.assert_called_once_with(complex_type, target, attr_type)
예제 #25
0
    def test_is_simple_type(self):
        obj = ClassFactory.elements(2)

        self.assertFalse(obj.is_simple_type)

        obj.attrs.pop()
        self.assertFalse(obj.is_simple_type)

        for tag in SIMPLE_TYPES:
            obj.attrs[0].tag = tag
            self.assertTrue(obj.is_simple_type)

        obj.extensions.append(ExtensionFactory.create())
        self.assertFalse(obj.is_simple_type)
예제 #26
0
    def test_reduce(self, mock_merge_attributes):
        first = ClassFactory.elements(2)
        second = first.clone()
        second.attrs.append(AttrFactory.create())
        third = second.clone()
        third.attrs.append(AttrFactory.create())
        fourth = ClassFactory.create()

        actual = ClassUtils.reduce([first, second, third, fourth])

        self.assertEqual([third, fourth], list(actual))
        mock_merge_attributes.assert_has_calls(
            [
                mock.call(third, first),
                mock.call(third, second),
            ]
        )
예제 #27
0
    def test_class_references(self):
        target = ClassFactory.elements(
            2,
            inner=ClassFactory.list(2, attrs=AttrFactory.list(1)),
            extensions=ExtensionFactory.list(1),
        )

        actual = ClassAnalyzer.class_references(target)
        # +1 target
        # +2 attrs
        # +2 attr types
        # +1 extension
        # +1 extension type
        # +2 inner classes
        # +2 inner classes attrs
        # +2 inner classes attr types
        self.assertEqual(13, len(actual))
        self.assertEqual(id(target), actual[0])
예제 #28
0
    def test_process(self, mock_process_attribute, mock_is_group):
        mock_is_group.side_effect = [
            True,
            False,
            True,
            True,
            False,
            False,
        ]
        target = ClassFactory.elements(2)

        self.processor.process(target)
        self.assertEqual(6, mock_is_group.call_count)

        mock_process_attribute.assert_has_calls([
            mock.call(target, target.attrs[0]),
            mock.call(target, target.attrs[0]),
            mock.call(target, target.attrs[1]),
        ])
예제 #29
0
    def test_group_compound_fields(self, mock_group_fields):
        target = ClassFactory.elements(8)
        # First group repeating
        target.attrs[0].restrictions.choice = "1"
        target.attrs[1].restrictions.choice = "1"
        target.attrs[1].restrictions.max_occurs = 2
        # Second group repeating
        target.attrs[2].restrictions.choice = "2"
        target.attrs[3].restrictions.choice = "2"
        target.attrs[3].restrictions.max_occurs = 2
        # Third group optional
        target.attrs[4].restrictions.choice = "3"
        target.attrs[5].restrictions.choice = "3"

        self.sanitizer.group_compound_fields(target)
        mock_group_fields.assert_has_calls([
            mock.call(target, target.attrs[0:2]),
            mock.call(target, target.attrs[2:4]),
        ])
예제 #30
0
    def test_add_attribute(self):
        target = ClassFactory.elements(2)
        attr = target.attrs[0].clone()
        attr.index += 1

        ElementMapper.add_attribute(target, attr)

        self.assertEqual(2, len(target.attrs))
        self.assertEqual(sys.maxsize, target.attrs[0].restrictions.max_occurs)
        self.assertEqual(2, len(target.attrs[0].types))
        self.assertFalse(target.attrs[0].restrictions.sequential)

        attr = target.attrs[1].clone()
        attr.restrictions.sequential = True
        ElementMapper.add_attribute(target, attr)
        self.assertTrue(target.attrs[1].restrictions.sequential)

        attr = AttrFactory.create()
        ElementMapper.add_attribute(target, attr)
        self.assertEqual(3, len(target.attrs))