def test_get_type_hints_with_typevars(self): A = TypeVar("A", str, int) B = TypeVar("B", bound=object) foo = make_dataclass("Foo", [("a", A), ("b", B), ("c", List[B])]) actual = self.ctx.get_type_hints(foo, None, return_input, return_input) expected = [ XmlVar(name="a", qname="a", element=True, types=[int, str]), XmlVar(name="b", qname="b", any_type=True, element=True, types=[object]), XmlVar( name="c", qname="c", any_type=True, list_element=True, element=True, types=[object], ), ] self.assertEqual(expected, list(actual))
def test_write_choice_with_raw_value(self): var = XmlVar( elements=True, name="compound", qname="compound", choices=[ XmlVar(element=True, qname="a", name="a", types=[int]), XmlVar(element=True, qname="b", name="b", types=[int], tokens=True), ], ) expected = [ (XmlWriterEvent.START, "a"), (XmlWriterEvent.DATA, "1"), (XmlWriterEvent.END, "a"), (XmlWriterEvent.START, "b"), (XmlWriterEvent.DATA, ["1", "2"]), (XmlWriterEvent.END, "b"), ] result = self.serializer.write_value([1, [1, 2]], var, "xsdata") self.assertIsInstance(result, Generator) self.assertEqual(expected, list(result))
def test_bind_choice_simple(self): var = XmlVar( elements=True, qname="compound", name="compound", choices=[ XmlVar(element=True, qname="int", name="int", types=[int]), XmlVar( element=True, qname="tokens", name="tokens", types=[int], tokens=True, ), XmlVar(element=True, qname="generic", name="generic", dataclass=True), XmlVar(element=True, qname="float", name="float", types=[float]), ], ) self.assertEqual(1.0, self.parser.bind_choice("1.0", var)) self.assertEqual(1, self.parser.bind_choice(1, var)) self.assertEqual([1], self.parser.bind_choice(["1"], var)) self.assertEqual("a", self.parser.bind_choice("a", var))
def write_choice(self, value: Any, var: XmlVar, namespace: NoneStr) -> Generator: """ Produce an events stream for the given value of a compound elements field. The value can be anything as long as we can match the qualified name or its type to a choice. """ if isinstance(value, DerivedElement): choice = var.find_choice(value.qname) value = value.value func = self.write_xsi_type if is_dataclass( value) else self.write_element elif isinstance(value, AnyElement) and value.qname: choice = var.find_choice(value.qname) func = self.write_any_type else: choice = var.find_value_choice(value) func = self.write_value if not choice: raise SerializerError( f"XmlElements undefined choice: `{var.name}` for `{type(value)}`" ) yield from func(value, choice, namespace)
def test_fetch_vars(self): elem = XmlVar(element=True, name="a", qname="a", types=[Foo], dataclass=True) wild = XmlVar(wildcard=True, name="a", qname="a", types=[Foo], dataclass=True) self.meta.vars.extend((wild, elem)) matching_vars = self.node.fetch_vars("a") self.assertIsInstance(matching_vars, Generator) self.assertEqual([(id(elem), elem), (None, wild)], list(matching_vars))
def test_fetch_vars_with_elements_var(self): elem = XmlVar(element=True, name="a", qname="a", types=[Foo], dataclass=True) elems = XmlVar(elements=True, name="compound", qname="compound", choices=[elem]) self.meta.vars.append(elems) matching_vars = self.node.fetch_vars("a") self.assertIsInstance(matching_vars, Generator) self.assertEqual((None, elem), next(matching_vars))
def test_property_clazz(self): var = XmlVar(name="foo", qname=QName("foo")) self.assertIsNone(var.clazz) var = XmlVar(name="foo", qname=QName("foo"), dataclass=True, types=[Fixture]) self.assertEqual(Fixture, var.clazz)
def test_bind_nillable_content(self): var = XmlVar(text=True, name="foo", qname="foo", types=[str], nillable=False) ns_map = {"foo": "bar"} node = PrimitiveNode(var, ns_map) objects = [] self.assertTrue(node.bind("foo", None, None, objects)) self.assertEqual("", objects[-1][1]) var.nillable = True self.assertTrue(node.bind("foo", None, None, objects)) self.assertIsNone(objects[-1][1])
def test_write_choice_when_no_matching_choice_exists(self): var = XmlVar( elements=True, name="compound", qname="compound", choices=[XmlVar(element=True, qname="a", name="a", types=[float])], ) with self.assertRaises(SerializerError) as cm: result = self.serializer.write_value(1, var, "xsdata") next(result) msg = "XmlElements undefined choice: `compound` for `<class 'int'>`" self.assertEqual(msg, str(cm.exception))
def test_get_type_hints(self): result = self.ctx.get_type_hints(BookForm, None) self.assertIsInstance(result, Iterator) expected = [ XmlVar(element=True, name="author", qname="author", types=[str]), XmlVar(element=True, name="title", qname="title", types=[str]), XmlVar(element=True, name="genre", qname="genre", types=[str]), XmlVar(element=True, name="price", qname="price", types=[float]), XmlVar(element=True, name="pub_date", qname="pub_date", types=[str]), XmlVar(element=True, name="review", qname="review", types=[str]), XmlVar(attribute=True, name="id", qname="id", types=[str]), XmlVar( attribute=True, name="lang", qname="lang", types=[str], init=False, default="en", ), ] result = list(result) self.assertEqual(expected, result) for var in result: self.assertFalse(var.dataclass) self.assertIsNone(var.clazz)
def test_child_when_failed_to_build_next_node(self, mock_build_node): mock_build_node.return_value = None self.meta.vars.append(XmlVar(element=True, name="a", qname="a")) self.meta.vars.append(XmlVar(wildcard=True, name="a", qname="a")) with self.assertRaises(ParserError) as cm: self.node.child("a", {}, {}, 0) self.assertEqual("Unknown property foo:a", str(cm.exception)) self.node.config.fail_on_unknown_properties = False actual = self.node.child("foobar", {}, {}, 0) self.assertIsInstance(actual, SkipNode)
def test_find_choice(self): choices = [ XmlVar(element=True, name="a", qname="{a}a"), XmlVar(element=True, name="b", qname="b"), ] var = XmlVar(elements=True, name="foo", qname="foo", choices=choices) self.assertFalse(var.matches("a")) self.assertIsNone(var.find_choice("a")) self.assertEqual(choices[0], var.find_choice("{a}a")) self.assertTrue(var.matches("{a}a")) self.assertEqual(choices[1], var.find_choice("b")) self.assertTrue(var.matches("b"))
def test_write_data(self): var = XmlVar(text=True, qname="a", name="a") expected = [(XmlWriterEvent.DATA, "123")] result = self.serializer.write_value("123", var, "xsdata") self.assertIsInstance(result, Generator) self.assertEqual(expected, list(result))
def test_bind_choice_generic_with_derived(self): var = XmlVar( elements=True, qname="compound", name="compound", choices=[ XmlVar(element=True, name="a", qname="a", types=[int]), XmlVar(element=True, name="b", qname="b", types=[float]), ], ) data = {"qname": "a", "value": 1, "substituted": True} self.assertEqual( DerivedElement(qname="a", value=1, substituted=True), self.parser.bind_choice(data, var), )
def test_write_any_type_with_primitive(self): var = XmlVar(wildcard=True, qname="a", name="a") expected = [(XmlWriterEvent.DATA, "str")] result = self.serializer.write_value("str", var, "xsdata") self.assertIsInstance(result, Generator) self.assertEqual(expected, list(result))
def test_write_any_type_with_any_element(self): var = XmlVar(wildcard=True, qname="a", name="a") value = AnyElement( qname="a", text="b", tail="c", attributes={ "d": 1, "e": 2 }, children=[AnyElement(text="g"), "h"], ) expected = [ (XmlWriterEvent.START, "a"), (XmlWriterEvent.ATTR, "d", 1), (XmlWriterEvent.ATTR, "e", 2), (XmlWriterEvent.DATA, "b"), (XmlWriterEvent.DATA, "g"), (XmlWriterEvent.DATA, "h"), (XmlWriterEvent.END, "a"), (XmlWriterEvent.DATA, "c"), ] result = self.serializer.write_value(value, var, "xsdata") self.assertIsInstance(result, Generator) self.assertEqual(expected, list(result))
def test_write_choice_with_generic_object(self): var = XmlVar( elements=True, name="compound", qname="compound", choices=[XmlVar(element=True, qname="a", name="a", types=[int])], ) value = AnyElement(qname="a", text="1") expected = [ (XmlWriterEvent.START, "a"), (XmlWriterEvent.DATA, "1"), (XmlWriterEvent.END, "a"), ] result = self.serializer.write_value(value, var, "xsdata") self.assertIsInstance(result, Generator) self.assertEqual(expected, list(result))
def test_write_choice_with_derived_dataclass(self): var = XmlVar( elements=True, name="compound", qname="compound", choices=[XmlVar(element=True, qname="a", name="a", types=[A])], ) value = DerivedElement(qname="a", value=A("foo")) expected = [ (XmlWriterEvent.START, "a"), (XmlWriterEvent.ATTR, "a0", "foo"), (XmlWriterEvent.END, "a"), ] result = self.serializer.write_value(value, var, "xsdata") self.assertIsInstance(result, Generator) self.assertEqual(expected, list(result))
def test_bind_derived_mode(self): var = XmlVar(text=True, name="foo", qname="foo", types=[int], derived=True) ns_map = {"foo": "bar"} node = PrimitiveNode(var, ns_map) objects = [] self.assertTrue(node.bind("foo", "13", "Impossible", objects)) self.assertEqual(DerivedElement("foo", 13), objects[-1][1])
def test_build_node_with_wildcard_var(self): var = XmlVar(wildcard=True, name="a", qname="a", types=[], dataclass=False) actual = self.node.build_node(var, {}, {}, 10) self.assertIsInstance(actual, WildcardNode) self.assertEqual(10, actual.position) self.assertEqual(var, actual.var)
def test_bind_choice_generic_with_derived(self): var = XmlVar( elements=True, qname="compound", name="compound", choices=[ XmlVar(element=True, name="a", qname="a", types=[int]), XmlVar(element=True, name="b", qname="b", types=[float]), ], ) self.assertEqual( DerivedElement(qname="a", value=1), self.parser.bind_choice({ "qname": "a", "value": 1 }, var), )
def test_build_node_with_primitive_var(self): var = XmlVar(text=True, name="a", qname="a", types=[int], default=100) attrs = {"a": "b"} ns_map = {"ns0": "xsdata"} actual = self.node.build_node(var, attrs, ns_map, 10) self.assertIsInstance(actual, PrimitiveNode) self.assertEqual(ns_map, actual.ns_map) self.assertEqual(var, actual.var)
def test_default_properties(self): var = XmlVar(name="foo", qname=QName("foo")) self.assertFalse(var.is_any_type) self.assertFalse(var.is_attribute) self.assertFalse(var.is_attributes) self.assertFalse(var.is_wildcard) self.assertFalse(var.is_element) self.assertFalse(var.is_text) self.assertFalse(var.is_tokens)
def test_child_unique_vars(self): single = XmlVar(element=True, name="a", qname="a", types=[Foo], dataclass=True) wildcard = XmlVar(wildcard=True, name="a", qname="a", types=[object]) self.meta.vars.append(single) self.meta.vars.append(wildcard) attrs = {"a": "b"} ns_map = {"ns0": "xsdata"} position = 1 actual = self.node.child("a", attrs, ns_map, position) self.assertIsInstance(actual, ElementNode) self.assertIn(id(single), self.node.assigned) actual = self.node.child("a", attrs, ns_map, position) self.assertIsInstance(actual, WildcardNode) self.assertNotIn(id(wildcard), self.node.assigned)
def test_bind_element_wild_text_when_element_has_no_text_and_tail(self): var = XmlVar(name="a", qname=QName("a")) meta = mock.Mock(XmlMeta) meta.find_var = MagicMock(return_value=var) elem = Element("foo") params = {} ParserUtils.bind_element_wild_text(params, meta, elem) self.assertEqual(0, len(params))
def test_bind_choice_generic_with_wildcard(self): var = XmlVar( elements=True, qname="compound", name="compound", choices=[ XmlVar(element=True, name="a", qname="a", types=[int]), XmlVar(element=True, name="b", qname="b", types=[float]), ], ) self.assertEqual( AnyElement(qname="a", text="1"), self.parser.bind_choice({ "qname": "a", "text": 1 }, var), )
def test_bind_choice_generic_with_unknown_qname(self): var = XmlVar(elements=True, qname="compound", name="compound") with self.assertRaises(ParserError) as cm: self.parser.bind_choice({"qname": "foo", "text": 1}, var) self.assertEqual( "XmlElements undefined choice: `compound` for qname `foo`", str(cm.exception), )
def test_build_node_with_any_type_var_with_datatype(self): var = XmlVar(element=True, name="a", qname="a", types=[object], any_type=True) attrs = {QNames.XSI_TYPE: "xs:hexBinary"} ns_map = {Namespace.XS.prefix: Namespace.XS.uri} actual = self.node.build_node(var, attrs, ns_map, 10) self.assertIsInstance(actual, StandardNode) self.assertEqual(ns_map, actual.ns_map) self.assertEqual(DataType.HEX_BINARY, actual.datatype) self.assertEqual(var.derived, actual.derived)
def test_write_tokens(self): var = XmlVar(element=True, qname="a", name="a", tokens=True) result = self.serializer.write_value([], var, "xsdata") self.assertIsInstance(result, Generator) self.assertEqual(0, len(list(result))) expected = [ (XmlWriterEvent.START, "a"), (XmlWriterEvent.DATA, ["1", QName("{a}b"), "3"]), (XmlWriterEvent.END, "a"), ] result = self.serializer.write_value([1, QName("{a}b"), 3], var, "xsdata") self.assertEqual(expected, list(result)) expected = [ (XmlWriterEvent.START, "a"), (XmlWriterEvent.DATA, ["1", "2", "3"]), (XmlWriterEvent.END, "a"), (XmlWriterEvent.START, "a"), (XmlWriterEvent.DATA, ["4", "5", "6"]), (XmlWriterEvent.END, "a"), ] result = self.serializer.write_value([[1, 2, 3], [4, 5, 6]], var, "xsdata") self.assertEqual(expected, list(result)) var = XmlVar(element=True, qname="a", name="a", tokens=True, nillable=True) expected = [ (XmlWriterEvent.START, "a"), (XmlWriterEvent.ATTR, QNames.XSI_NIL, "true"), (XmlWriterEvent.DATA, []), (XmlWriterEvent.END, "a"), ] result = self.serializer.write_value([], var, "xsdata") self.assertEqual(expected, list(result))
def test_build_node_with_any_type_var_with_no_xsi_type(self): var = XmlVar(element=True, name="a", qname="a", types=[object], any_type=True) attrs = {} actual = self.node.build_node(var, attrs, {}, 10) self.assertIsInstance(actual, WildcardNode) self.assertEqual(10, actual.position) self.assertEqual(var, actual.var) self.assertEqual(attrs, actual.attrs) self.assertEqual({}, actual.ns_map)