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)
def test_process_classes_with_print_false( self, mock_assign_packages, mock_analyze_classes, mock_writer_write, mock_logger_into, ): schema_classes = ClassFactory.list(3) analyzer_classes = ClassFactory.list(2) mock_analyze_classes.return_value = analyzer_classes self.transformer.print = False self.transformer.class_map = { "http://xsdata/foo.xsd": schema_classes[:1], "http://xsdata/bar.xsd": schema_classes[1:], } self.transformer.process_classes() mock_assign_packages.assert_called_once_with() mock_analyze_classes.assert_called_once_with(schema_classes) mock_writer_write.assert_called_once_with(analyzer_classes) mock_logger_into.assert_has_calls([ mock.call("Analyzer input: %d main and %d inner classes", 3, 0), mock.call("Analyzer output: %d main and %d inner classes", 2, 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), ] )
def test_create_substitutions(self, mock_create_substitution): ns = "xsdata" classes = [ ClassFactory.create( substitutions=[build_qname(ns, "foo"), build_qname(ns, "bar")], abstract=True, ), ClassFactory.create(substitutions=[build_qname(ns, "foo")], abstract=True), ] reference_attrs = AttrFactory.list(3) mock_create_substitution.side_effect = reference_attrs self.processor.container.extend(classes) self.processor.create_substitutions() expected = { build_qname(ns, "foo"): [reference_attrs[0], reference_attrs[2]], build_qname(ns, "bar"): [reference_attrs[1]], } self.assertEqual(expected, self.processor.substitutions) mock_create_substitution.assert_has_calls( [mock.call(classes[0]), mock.call(classes[0]), mock.call(classes[1])] )
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)
def test_get_or_create_inner_class(self): target = ClassFactory.create(module="foo", package=None, ns_map={"foo": "bar"}) actual = DefinitionsMapper.build_inner_class(target, "body") expected = ClassFactory.create( qname="body", tag=Tag.BINDING_MESSAGE, module=target.module, package=None, ns_map=target.ns_map, ) self.assertEqual(expected, actual) self.assertIn(actual, target.inner) self.assertIsNot(actual.ns_map, target.ns_map) expected_attr = DefinitionsMapper.build_attr("body", "body", forward=True) self.assertEqual(expected_attr, target.attrs[0]) repeat = DefinitionsMapper.build_inner_class(target, "body") self.assertIs(repeat, actual)
def test_process_enum_extension_with_complex_source(self): source = ClassFactory.create( tag=Tag.COMPLEX_TYPE, attrs=[ AttrFactory.create(tag=Tag.ATTRIBUTE), AttrFactory.create(tag=Tag.RESTRICTION), ], extensions=ExtensionFactory.list(2), status=Status.PROCESSED, ) target = ClassFactory.enumeration(1) target.attrs[0].default = "Yes" extension = ExtensionFactory.reference(source.qname) target.extensions.append(extension) expected = target.clone() self.processor.container.add(source) self.processor.container.add(target) self.processor.process_dependency_extension(target, extension) expected.attrs = [attr.clone() for attr in source.attrs] expected.extensions = [ext.clone() for ext in source.extensions] expected.attrs[1].default = "Yes" expected.attrs[1].fixed = True self.assertEqual(expected, target) self.assertIsNone(target.attrs[0].default) self.assertFalse(target.attrs[0].fixed) self.assertEqual("Yes", target.attrs[1].default) self.assertTrue(target.attrs[1].fixed)
def test_build_envelope_fault(self): body = ClassFactory.create(qname="Body") target = ClassFactory.create() target.inner.append(body) port_type_operation = PortTypeOperation() definitions = Definitions() DefinitionsMapper.build_envelope_fault(definitions, port_type_operation, target) expected_fault_attr = DefinitionsMapper.build_attr( "Fault", body.inner[0].qname, forward=True, namespace=target.namespace) str_qname = str(DataType.STRING) expected_fault_attrs = [ DefinitionsMapper.build_attr(name, str_qname, native=True, namespace="") for name in ["faultcode", "faultstring", "faultactor", "detail"] ] self.assertEqual(1, len(body.attrs)) self.assertEqual(expected_fault_attr, body.attrs[0]) self.assertEqual(expected_fault_attrs, body.inner[0].attrs)
def test_build_class_attribute_from_dict(self): target = ClassFactory.create() data = {"sub1": 1, "sub2": "value"} DictMapper.build_class_attribute(target, "a", data) expected = AttrFactory.create( name="a", tag=Tag.ELEMENT, types=[AttrTypeFactory.create(qname="a", forward=True)], ) expected_inner = ClassFactory.create( qname="a", tag=Tag.ELEMENT, module="", ns_map={}, attrs=[ AttrFactory.native(DataType.SHORT, name="sub1"), AttrFactory.native(DataType.STRING, name="sub2"), ], ) self.assertEqual(expected, target.attrs[0]) self.assertEqual(expected_inner, target.inner[0]) self.assertEqual(1, len(target.inner))
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)
def test_find_enum(self): native_type = AttrTypeFactory.create() matching_external = AttrTypeFactory.create("foo") missing_external = AttrTypeFactory.create("bar") enumeration = ClassFactory.enumeration(1, qname="foo") inner = ClassFactory.enumeration(1, qname="foobar") target = ClassFactory.create( attrs=[ AttrFactory.create(types=[ native_type, matching_external, missing_external, ]) ], inner=[inner], ) self.sanitizer.container.extend([target, enumeration]) actual = self.sanitizer.find_enum(native_type) self.assertIsNone(actual) actual = self.sanitizer.find_enum(matching_external) self.assertEqual(enumeration, actual) actual = self.sanitizer.find_enum(missing_external) self.assertIsNone(actual)
def test_render(self, mock_render_module, mock_render_package): classes = [ ClassFactory.create(package="foo.bar"), ClassFactory.create(package="bar.foo"), ClassFactory.create(package="thug.life"), ] mock_render_module.return_value = "module" mock_render_package.return_value = "package" iterator = self.generator.render(classes) cwd = Path.cwd() actual = [(out.path, out.title, out.source) for out in iterator] expected = [ (cwd.joinpath("foo/bar/__init__.py"), "init", "package"), (cwd.joinpath("foo/__init__.py"), "init", "# nothing here\n"), (cwd.joinpath("bar/foo/__init__.py"), "init", "package"), (cwd.joinpath("bar/__init__.py"), "init", "# nothing here\n"), (cwd.joinpath("thug/life/__init__.py"), "init", "package"), (cwd.joinpath("thug/__init__.py"), "init", "# nothing here\n"), (cwd.joinpath("foo/bar/tests.py"), "foo.bar.tests", "module"), (cwd.joinpath("bar/foo/tests.py"), "bar.foo.tests", "module"), (cwd.joinpath("thug/life/tests.py"), "thug.life.tests", "module"), ] self.assertEqual(expected, actual) mock_render_package.assert_has_calls([mock.call([x]) for x in classes]) mock_render_module.assert_has_calls( [mock.call(mock.ANY, [x]) for x in classes])
def test_render_package(self): classes = [ ClassFactory.create(qname="a", package="foo"), ClassFactory.create(qname="b", package="foo"), ClassFactory.create(qname="c", package="foo"), ClassFactory.create(qname="a", package="foo", module="bar"), ] random.shuffle(classes) actual = self.generator.render_package(classes) expected = "\n".join([ "from foo.bar import A as BarA", "from foo.tests import (", " A as TestsA,", " B,", " C,", ")", "", "__all__ = [", ' "BarA",', ' "TestsA",', ' "B",', ' "C",', "]", "", ]) self.assertEqual(expected, actual)
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)])
def test_rename_class_dependencies(self): attr_type = AttrTypeFactory.create("{foo}bar") target = ClassFactory.create( extensions=[ ExtensionFactory.create(), ExtensionFactory.create(attr_type.clone()), ], attrs=[ AttrFactory.create(), AttrFactory.create( types=[AttrTypeFactory.create(), attr_type.clone()]), ], inner=[ ClassFactory.create( extensions=[ExtensionFactory.create(attr_type.clone())], attrs=[ AttrFactory.create(), AttrFactory.create(types=[ AttrTypeFactory.create(), attr_type.clone() ]), ], ) ], ) self.sanitizer.rename_class_dependencies(target, "{foo}bar", "thug") dependencies = set(target.dependencies()) self.assertNotIn("{foo}bar", dependencies) self.assertIn("thug", dependencies)
def test_map_binding_operation_messages_with_style_rpc( self, mock_build_envelope_class, mock_build_message_class): definitions = Definitions() operation = BindingOperation() port_operation = PortTypeOperation() name = "Add" namespace = "someNS" target = ClassFactory.create() message = ClassFactory.create() style = "rpc" mock_build_message_class.return_value = message mock_build_envelope_class.return_value = target operation.input = BindingMessage() port_operation.input = PortTypeMessage() result = DefinitionsMapper.map_binding_operation_messages( definitions, operation, port_operation, name, style, namespace) self.maxDiff = None self.assertEqual([message, target], list(result)) mock_build_message_class.assert_called_once_with( definitions, port_operation.input) mock_build_envelope_class.assert_called_once_with( definitions, operation.input, port_operation.input, f"{name}_input", style, namespace, )
def test_copy_attributes(self, mock_clone_attribute, mock_copy_inner_classes): mock_clone_attribute.side_effect = lambda x, y: x.clone() target = ClassFactory.create( attrs=[AttrFactory.create(name="a"), AttrFactory.create(name="b")] ) source = ClassFactory.create( attrs=[ AttrFactory.create(name="c", index=sys.maxsize), AttrFactory.create(name="a"), AttrFactory.create(name="b"), AttrFactory.create(name="d"), ] ) extension = ExtensionFactory.create(AttrTypeFactory.create(qname="foo")) target.extensions.append(extension) ClassUtils.copy_attributes(source, target, extension) self.assertEqual(["a", "b", "d", "c"], [attr.name for attr in target.attrs]) mock_copy_inner_classes.assert_has_calls( [ mock.call(source, target, source.attrs[0]), mock.call(source, target, source.attrs[3]), ] ) mock_clone_attribute.assert_has_calls( [ mock.call(source.attrs[0], extension.restrictions), mock.call(source.attrs[3], extension.restrictions), ] )
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])
def test_initialize(self): classes = [ ClassFactory.create(qname="{xsdata}foo", tag=Tag.ELEMENT), ClassFactory.create(qname="{xsdata}foo", tag=Tag.COMPLEX_TYPE), ClassFactory.create(qname="{xsdata}foobar", tag=Tag.COMPLEX_TYPE), ] container = ClassContainer() container.extend(classes) expected = { "{xsdata}foo": classes[:2], "{xsdata}foobar": classes[2:], } self.assertEqual(2, len(container.data)) self.assertEqual(expected, container.data) self.assertEqual( [ "AttributeGroupHandler", "ClassExtensionHandler", "ClassEnumerationHandler", "AttributeSubstitutionHandler", "AttributeTypeHandler", "AttributeMergeHandler", "AttributeMixedContentHandler", "AttributeSanitizerHandler", ], [x.__class__.__name__ for x in container.processors], )
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)
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]), ])
def test_rename_classes_protects_single_element(self, mock_rename_class): classes = [ ClassFactory.create(qname="_a", tag=Tag.ELEMENT), ClassFactory.create(qname="a", tag=Tag.COMPLEX_TYPE), ] self.sanitizer.rename_classes(classes) mock_rename_class.assert_called_once_with(classes[1])
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)
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)
def test_copy_inner_class_with_missing_inner(self): source = ClassFactory.create() target = ClassFactory.create() attr = AttrFactory.create() attr_type = AttrTypeFactory.create(forward=True, qname=target.qname) with self.assertRaises(CodeGenerationError): ClassUtils.copy_inner_class(source, target, attr, attr_type)
def test_process(self): target = ClassFactory.create(inner=ClassFactory.list(2)) self.container.add(target) self.container.process_class(target) self.assertEqual(Status.PROCESSED, target.status) self.assertEqual(Status.PROCESSED, target.inner[0].status) self.assertEqual(Status.PROCESSED, target.inner[1].status)
def test_dependencies(self): obj = ClassFactory.create( attrs=[ AttrFactory.create( types=[AttrTypeFactory.native(DataType.DECIMAL)]), AttrFactory.create( types=[ AttrTypeFactory.create( qname=build_qname(Namespace.XS.uri, "annotated"), forward=True, ) ], choices=[ AttrFactory.create( name="x", types=[ AttrTypeFactory.create(qname="choiceAttr"), AttrTypeFactory.native(DataType.STRING), ], ), AttrFactory.create( name="x", types=[ AttrTypeFactory.create(qname="choiceAttrTwo"), AttrTypeFactory.create(qname="choiceAttrEnum"), ], ), ], ), AttrFactory.create(types=[ AttrTypeFactory.create( qname=build_qname(Namespace.XS.uri, "openAttrs")), AttrTypeFactory.create( qname=build_qname(Namespace.XS.uri, "localAttribute")), ]), ], extensions=[ ExtensionFactory.reference( build_qname(Namespace.XS.uri, "foobar")), ExtensionFactory.reference( build_qname(Namespace.XS.uri, "foobar")), ], inner=[ ClassFactory.create(attrs=AttrFactory.list( 2, types=AttrTypeFactory.list(1, qname="{xsdata}foo"))) ], ) expected = [ "choiceAttr", "choiceAttrTwo", "choiceAttrEnum", "{http://www.w3.org/2001/XMLSchema}openAttrs", "{http://www.w3.org/2001/XMLSchema}localAttribute", "{http://www.w3.org/2001/XMLSchema}foobar", "{xsdata}foo", ] self.assertCountEqual(expected, list(obj.dependencies()))
def test_map_binding(self, mock_attributes, mock_find_operation, mock_map_binding_operation): definitions = Definitions() port_type = PortType(name="Calc") binding = Binding( type="zaa:zoo", operations=[ BindingOperation(name="ADD"), BindingOperation(name="SUB") ], ) port_type_add = PortTypeOperation(name="PortAdd") port_type_sub = PortTypeOperation(name="PortSub") classes = [ ClassFactory.list(2), ClassFactory.list(2), ] mock_map_binding_operation.side_effect = classes mock_find_operation.side_effect = [port_type_add, port_type_sub] mock_attributes.side_effect = [ { "soapAction": "add" }, { "soapAction": "sub" }, ] config = {"foo": "bar"} result = DefinitionsMapper.map_binding(definitions, binding, port_type, config) self.assertIsInstance(result, Generator) self.assertEqual(classes[0] + classes[1], list(result)) mock_find_operation.assert_has_calls( [mock.call("ADD"), mock.call("SUB")]) self.assertEqual(2, mock_attributes.call_count) config_add = {"soapAction": "add", **config} config_sub = {"soapAction": "sub", **config} mock_map_binding_operation.assert_has_calls([ mock.call( definitions, binding.operations[0], port_type_add, config_add, "Calc", ), mock.call( definitions, binding.operations[1], port_type_sub, config_sub, "Calc", ), ])
def test_property_is_complex(self): obj = ClassFactory.create(tag=Tag.ELEMENT) self.assertTrue(obj.is_complex) obj = ClassFactory.create(tag=Tag.COMPLEX_TYPE) self.assertTrue(obj.is_complex) obj = ClassFactory.create(tag=Tag.SIMPLE_TYPE) self.assertFalse(obj.is_complex)
def test_filter_classes_with_only_simple_types(self, mock_class_should_generate): mock_class_should_generate.return_value = False classes = [ClassFactory.enumeration(2), ClassFactory.simple_type()] container = ClassContainer() container.extend(classes) container.filter_classes() self.assertEqual(classes, container.class_list)