示例#1
0
    def test_render(self):
        classes = [
            ClassFactory.elements(2),
            ClassFactory.elements(3),
        ]

        iterator = PlantUmlGenerator().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("foo/tests.pu",
                         str(actual[0][0].relative_to(Path.cwd())))

        output = """@startuml

class class_B {
    +attr_B : string
    +attr_C : string
}
class class_C {
    +attr_D : string
    +attr_E : string
    +attr_F : string
}

@enduml"""
        self.assertEqual(output, actual[0][2])
示例#2
0
    def test_process_class(
        self,
        mock_process_attribute_default,
        mock_process_attribute_restrictions,
        mock_process_attribute_name,
        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_name.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)])
示例#3
0
    def test_flatten_extension_simple_when_source_and_target_are_not_enumerations(
            self, mock_copy_attributes):
        source = ClassFactory.elements(2)
        target = ClassFactory.elements(1)
        extension = ExtensionFactory.create()

        self.analyzer.flatten_extension_simple(source, target, extension)
        mock_copy_attributes.assert_called_once_with(source, target, extension)
示例#4
0
    def test_find_simple_class(self):
        a = ClassFactory.enumeration(1, name="a")
        b = ClassFactory.create(name="b", type=SimpleType)
        c = ClassFactory.elements(1, name="c", abstract=True)
        d = ClassFactory.elements(1, name="d")

        self.analyzer.create_class_index([a, b, c, d])

        self.assertEqual(a, self.analyzer.find_simple_class(a.source_qname()))
        self.assertEqual(b, self.analyzer.find_simple_class(b.source_qname()))
        self.assertEqual(c, self.analyzer.find_simple_class(c.source_qname()))
        self.assertIsNone(self.analyzer.find_simple_class(d.source_qname()))
    def test_process_attribute(self, mock_find):
        target = ClassFactory.elements(2)
        mock_find.side_effect = [-1, 2]

        first_attr = target.attrs[0]
        second_attr = target.attrs[1]
        first_attr.restrictions.max_occurs = 2

        attr_name = first_attr.name
        attr_qname = target.source_qname(attr_name)
        reference_attrs = AttrFactory.list(2)

        self.processor.create_substitutions()
        self.processor.substitutions[attr_qname] = reference_attrs
        self.processor.process_attribute(target, first_attr)

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

        self.assertEqual(reference_attrs[0], target.attrs[0])
        self.assertIsNot(reference_attrs[0], target.attrs[0])
        self.assertEqual(reference_attrs[1], target.attrs[3])
        self.assertIsNot(reference_attrs[1], target.attrs[3])
        self.assertEqual(2, target.attrs[0].restrictions.max_occurs)
        self.assertEqual(2, target.attrs[3].restrictions.max_occurs)

        self.processor.process_attribute(target, second_attr)
        self.assertEqual(4, len(target.attrs))
示例#6
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)
示例#7
0
    def test_process_extension_native(self, mock_create_default_attribute):
        extension = ExtensionFactory.create()
        target = ClassFactory.elements(1)

        self.processor.process_native_extension(target, extension)
        mock_create_default_attribute.assert_called_once_with(
            target, extension)
示例#8
0
    def test_add_substitution_attrs(self, mock_find_attribute):
        target = ClassFactory.elements(2)
        mock_find_attribute.side_effect = [-1, 2]

        first_attr = target.attrs[0]
        second_attr = target.attrs[1]
        first_attr.restrictions.max_occurs = 2

        attr_name = first_attr.name
        attr_qname = target.source_qname(attr_name)
        reference_attrs = AttrFactory.list(2)

        self.analyzer.substitutions_index[attr_qname] = reference_attrs
        self.analyzer.add_substitution_attrs(target, first_attr)

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

        self.assertEqual(reference_attrs[0], target.attrs[0])
        self.assertIsNot(reference_attrs[0], target.attrs[0])
        self.assertEqual(reference_attrs[1], target.attrs[3])
        self.assertIsNot(reference_attrs[1], target.attrs[3])
        self.assertEqual(2, target.attrs[0].restrictions.max_occurs)
        self.assertEqual(2, target.attrs[3].restrictions.max_occurs)

        second_attr.wildcard = True
        self.analyzer.add_substitution_attrs(target, second_attr)
        self.assertEqual(4, len(target.attrs))

        self.analyzer.add_substitution_attrs(target, AttrFactory.enumeration())
        self.assertEqual(4, len(target.attrs))
示例#9
0
    def test_flatten_extension_with_native_type_and_target_not_enumeration(
        self, mock_create_default_attribute
    ):
        extension = ExtensionFactory.create(type=AttrTypeFactory.xs_string())
        target = ClassFactory.elements(1, extensions=[extension])

        self.analyzer.flatten_extension(target, extension)
        mock_create_default_attribute.assert_called_once_with(target, extension)
示例#10
0
    def test_find_repeat_on_condition_and_not_processed(
            self, mock_process_class):
        first = ClassFactory.elements(2, qname="a")
        second = ClassFactory.elements(2, qname="a")
        self.container.extend([first, second])

        def process_class(x: Class):
            x.status = Status.PROCESSED
            if x is first:
                first.attrs.clear()

        mock_process_class.side_effect = process_class

        self.assertEqual(
            second,
            self.container.find(first.qname, lambda x: len(x.attrs) == 2),
        )
示例#11
0
    def test_flatten_extension_native_and_target_no_enumeration(
            self, mock_create_default_attribute):
        extension = ExtensionFactory.create()
        target = ClassFactory.elements(1)

        self.analyzer.flatten_extension_native(target, extension)
        mock_create_default_attribute.assert_called_once_with(
            target, extension)
示例#12
0
    def test_flatten_extension_with_native_type(self,
                                                mock_flatten_extension_native):
        extension = ExtensionFactory.create(type=AttrTypeFactory.xs_string())
        target = ClassFactory.elements(1, extensions=[extension])

        self.analyzer.flatten_extension(target, extension)
        mock_flatten_extension_native.assert_called_once_with(
            target, extension)
示例#13
0
    def test_find_attr_simple_type(self):
        a = ClassFactory.enumeration(1, name="a")
        b = ClassFactory.elements(1, name="b", abstract=True)
        c = ClassFactory.elements(1, name="c")
        type_a = AttrTypeFactory.create(name="a")
        type_b = AttrTypeFactory.create(name="b")
        type_c = AttrTypeFactory.create(name="c")

        self.analyzer.create_class_index([a, b, c])

        self.assertIsNone(self.analyzer.find_attr_simple_type(
            a, type_a))  # Enumeration
        self.assertIsNone(self.analyzer.find_attr_simple_type(
            a, type_c))  # Complex
        self.assertIsNone(self.analyzer.find_attr_simple_type(
            b, type_b))  # Source is target
        self.assertEqual(b, self.analyzer.find_attr_simple_type(a, type_b))
示例#14
0
    def test_process_extension_with_dependency_type(
            self, mock_process_dependency_extension):
        extension = ExtensionFactory.create(type=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)
示例#15
0
    def test_process_simple_dependency_no_source_attributes(self):
        source = ClassFactory.create()
        target = ClassFactory.elements(1)
        attr = target.attrs[0]
        self.processor.process_simple_dependency(source, target, attr,
                                                 attr.types[0])

        self.assertEqual("string", attr.types[0].name)
示例#16
0
    def test_flatten_extension_simple_when_source_is_enumeration_and_target_is_not(
        self, mock_create_default_attribute
    ):
        source = ClassFactory.enumeration(2)
        target = ClassFactory.elements(1)
        extension = ExtensionFactory.create()

        self.analyzer.flatten_extension_simple(source, target, extension)
        mock_create_default_attribute.assert_called_once_with(target, extension)
示例#17
0
    def test_class_docstring_with_class_help(self):
        target = ClassFactory.elements(2, help="Help Me!")

        expected = '''"""Help Me!

:ivar attr_b:
:ivar attr_c:
"""'''
        self.assertEqual(expected, class_docstring(target))
示例#18
0
    def test_copy_group_attributes(self, mock_clone_attribute,
                                   mock_copy_inner_classes):
        mock_clone_attribute.side_effect = lambda x, y, z: x.clone()
        source = ClassFactory.elements(2)
        source.inner.append(ClassFactory.create())
        target = ClassFactory.elements(3)
        attrs = list(target.attrs)
        attrs[1].name = "foo: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_called_once_with(source, target)
        mock_clone_attribute.assert_has_calls([
            mock.call(source.attrs[0], attrs[1].restrictions, "foo"),
            mock.call(source.attrs[1], attrs[1].restrictions, "foo"),
        ])
示例#19
0
    def test_copy_extension_type(self):
        extension = ExtensionFactory.create()
        target = ClassFactory.elements(2)
        target.extensions.append(extension)

        ClassExtensionHandler.copy_extension_type(target, extension)

        self.assertEqual(extension.type, target.attrs[0].types[1])
        self.assertEqual(extension.type, target.attrs[1].types[1])
        self.assertEqual(0, len(target.extensions))
示例#20
0
    def test_flatten_extension_simple_when_target_is_enumeration_and_source_is_not(
            self, mock_create_default_attribute, mock_copy_attributes):
        extension = ExtensionFactory.create()
        source = ClassFactory.elements(2)
        target = ClassFactory.enumeration(1, extensions=[extension])

        self.analyzer.flatten_extension_simple(source, target, extension)
        self.assertEqual(0, mock_create_default_attribute.call_count)
        self.assertEqual(0, mock_copy_attributes.call_count)
        self.assertEqual(0, len(target.extensions))
示例#21
0
    def test_process_simple_dependency(self, mock_copy_inner_classes):
        source = ClassFactory.elements(1, qname="Foobar")
        source.attrs[0].restrictions.max_length = 100
        source.attrs[0].restrictions.min_length = 1

        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.process_simple_dependency(source, target, attr,
                                                 attr.types[0])

        self.assertEqual("string", attr.types[0].name)
        self.assertEqual(Restrictions(min_length=2, max_length=100),
                         attr.restrictions)
        mock_copy_inner_classes.assert_called_once_with(source, target)
示例#22
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))
示例#23
0
    def test_process(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)
示例#24
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)
    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.type.__name__,
        )

        self.assertEqual(expected, actual)
示例#26
0
    def test_sanitize_attributes(
        self,
        mock_sanitize_attribute,
        mock_sanitize_restrictions,
        mock_sanitize_attribute_sequence,
        mock_sanitize_attribute_name,
    ):

        target = ClassFactory.elements(3)
        inner = ClassFactory.elements(2)
        target.inner.append(inner)

        ClassUtils.sanitize_attributes(target)
        ClassUtils.sanitize_attributes(ClassFactory.create())

        self.assertEqual(5, mock_sanitize_attribute.call_count)
        mock_sanitize_attribute.assert_has_calls([
            mock.call(target.attrs[0]),
            mock.call(target.attrs[1]),
            mock.call(target.attrs[2]),
            mock.call(target.inner[0].attrs[0]),
            mock.call(target.inner[0].attrs[1]),
        ])
        mock_sanitize_restrictions.assert_has_calls([
            mock.call(target.attrs[0].restrictions),
            mock.call(target.attrs[1].restrictions),
            mock.call(target.attrs[2].restrictions),
            mock.call(target.inner[0].attrs[0].restrictions),
            mock.call(target.inner[0].attrs[1].restrictions),
        ])

        expected_second = [
            mock.call(target.attrs, 0),
            mock.call(target.attrs, 1),
            mock.call(target.attrs, 2),
            mock.call(target.inner[0].attrs, 0),
            mock.call(target.inner[0].attrs, 1),
        ]
        mock_sanitize_attribute_sequence.assert_has_calls(expected_second)
        mock_sanitize_attribute_name.assert_has_calls(expected_second)
示例#27
0
    def test_process_simple_dependency_with_more_than_one_attribute(self):
        source = ClassFactory.create(type=SimpleType,
                                     attrs=AttrFactory.list(2))
        target = ClassFactory.elements(1)
        attr = target.attrs[0]
        attr_type = attr.types[0]

        with self.assertRaises(AnalyzerValueError) as cm:
            self.processor.process_simple_dependency(source, target, attr,
                                                     attr_type)

        self.assertEqual("SimpleType with more than one attribute: `class_B`",
                         str(cm.exception))
示例#28
0
    def test_process_attributes_with_exploit_names(
        self,
        mock_process_attribute,
        mock_has_duplicate_attrs,
        mock_sanitize_attribute_names,
        mock_hash_attributes_names,
        mock_unset_attributes_local_names,
    ):
        obj = ClassFactory.elements(3)
        mock_has_duplicate_attrs.return_value = True
        generator.process_attributes(obj, ["a", "b"])
        mock_process_attribute.assert_has_calls(
            [mock.call(obj, attr, ["a", "b"]) for attr in obj.attrs])

        mock_sanitize_attribute_names.assert_called_once_with(obj)
        mock_unset_attributes_local_names.assert_called_once_with(obj)
        mock_hash_attributes_names.assert_called_once_with(obj)
示例#29
0
    def test_process_attributes_with_duplicate_names(
        self,
        mock_process_attribute,
        mock_has_duplicate_attrs,
        mock_sanitize_attribute_names,
        mock_hash_attributes_names,
        mock_unset_attributes_local_names,
    ):
        obj = ClassFactory.elements(3)
        mock_has_duplicate_attrs.side_effect = [True, False]
        generator.process_attributes(obj, ["a", "b"])
        mock_process_attribute.assert_has_calls(
            [mock.call(obj, attr, ["a", "b"]) for attr in obj.attrs])

        mock_sanitize_attribute_names.assert_called_once_with(obj)
        mock_unset_attributes_local_names.assert_called_once_with(obj)
        self.assertEqual(0, mock_hash_attributes_names.call_count)
示例#30
0
    def test_flatten_class(
        self,
        mock_flatten_enumeration_unions,
        mock_expand_attribute_group,
        mock_flatten_extension,
        mock_flatten_attribute_types,
        mock_add_substitution_attrs,
        mock_create_mixed_attribute,
        mock_merge_duplicate_attributes,
    ):
        inner = ClassFactory.list(2)
        extensions = ExtensionFactory.list(2)
        target = ClassFactory.elements(2, inner=inner, extensions=extensions)

        self.analyzer.flatten_class(target)

        mock_flatten_enumeration_unions.assert_has_calls(
            [mock.call(target), mock.call(inner[0]), mock.call(inner[1])]
        )

        mock_expand_attribute_group.assert_has_calls(
            [mock.call(target, target.attrs[0]), mock.call(target, target.attrs[1])]
        )

        mock_flatten_extension.assert_has_calls(
            [
                mock.call(target, target.extensions[1]),
                mock.call(target, target.extensions[0]),
            ]
        )

        mock_flatten_attribute_types.assert_has_calls(
            [mock.call(target, target.attrs[0]), mock.call(target, target.attrs[1])]
        )

        mock_add_substitution_attrs.assert_has_calls(
            [mock.call(target, target.attrs[0]), mock.call(target, target.attrs[1])]
        )

        mock_create_mixed_attribute.assert_has_calls(
            [mock.call(target), mock.call(inner[0]), mock.call(inner[1])]
        )

        mock_merge_duplicate_attributes.assert_has_calls(
            [mock.call(target), mock.call(inner[0]), mock.call(inner[1])]
        )