def test_parse_any_element(self): comment = Comment("foo") self.assertIsNone(XmlParser.parse_any_element(comment)) element = Element("foo") element.set("a", "1") element.set("b", "2") element.set( QName(Namespace.XSI.uri, "type").text, QName(Namespace.XS.uri, "float").text) element.text = "yes" element.tail = "no" actual = XmlParser.parse_any_element(element) expected = AnyElement( qname=element.tag, text="yes", tail="no", attributes={ "a": "1", "b": "2", QName(Namespace.XSI.uri, "type"): QName(Namespace.XS.uri, "float"), }, ns_map=element.nsmap, ) self.assertEqual(expected, actual) actual = XmlParser.parse_any_element(element, False) self.assertIsNone(actual.qname)
def test_parse_with_fail_on_unknown_properties_false(self): path = fixtures_dir.joinpath("books/books.xml") @dataclass class Book: author: str = field(metadata=dict(type="Element")) @dataclass class MyBooks: class Meta: name = "books" book: List[Book] = field(default_factory=list, metadata=dict(type="Element")) config = ParserConfig(fail_on_unknown_properties=False) parser = XmlParser(config=config) actual = parser.from_path(path, MyBooks) expected = { "book": [{ "author": "Hightower, Kim" }, { "author": "Nagata, Suanne" }] } self.assertEqual(expected, asdict(actual))
def test_element_text_and_tail(self): element = Element("foo") text, tail = XmlParser.element_text_and_tail(element) self.assertIsNone(text) self.assertIsNone(tail) element.text = " \n " element.tail = " \n " text, tail = XmlParser.element_text_and_tail(element) self.assertIsNone(text) self.assertIsNone(tail) element.text = " foo " element.tail = " bar " text, tail = XmlParser.element_text_and_tail(element) self.assertEqual("foo", text) self.assertEqual("bar", tail)
def test_parse_with_fail_on_unknown_properties_false(self): xml = ('<?xml version="1.0" encoding="UTF-8"?>\n' "<books>\n" ' <book id="bk001">\n' " <author>Hightower, Kim</author>\n" " <title>The First Book</title>\n" " </book>\n" ' <book id="bk002">\n' " <author>Nagata, Suanne</author>\n" " <title>Becoming Somebody</title>\n" " </book>\n" "</books>\n") @dataclass class Book: author: str = field(metadata=dict(type="Element")) @dataclass class MyBooks: class Meta: name = "books" book: List[Book] = field(default_factory=list, metadata=dict(type="Element")) config = ParserConfig(fail_on_unknown_properties=False) parser = XmlParser(config=config) actual = parser.from_string(xml, MyBooks) expected = { "book": [{ "author": "Hightower, Kim" }, { "author": "Nagata, Suanne" }] } self.assertEqual(expected, asdict(actual))
def test_parse(self): xml = ( '<?xml version="1.0" encoding="UTF-8"?>\n' '<brk:books xmlns:brk="urn:books">\n' ' <book id="bk001">\n' " <author>Hightower, Kim</author>\n" " <title>The First Book</title>\n" " <genre>Fiction</genre>\n" " <price>44.95</price>\n" " <pub_date>2000-10-01</pub_date>\n" " <review>An amazing story of nothing.</review>\n" " </book>\n" ' <book id="bk002">\n' " <author>Nagata, Suanne</author>\n" " <title>Becoming Somebody</title>\n" " <genre>Biography</genre>\n" " <review>A masterpiece of the fine art of gossiping.</review>\n" " </book>\n" "</brk:books>\n") parser = XmlParser() actual = parser.from_string(xml, Books) self.assertEqual(self.books, actual) self.assertEqual({"brk": "urn:books"}, parser.namespaces.ns_map)
class XmlParserTests(TestCase): def setUp(self): super().setUp() self.parser = XmlParser() self.parser.objects = [(x, x) for x in "abcde"] @mock.patch.object(XmlParser, "emit_event") def test_start(self, mock_emit_event): attrs = {"a": "b"} queue = [] self.parser.start(Books, queue, [], "{urn:books}books", attrs, {}) self.assertEqual(1, len(queue)) mock_emit_event.assert_called_once_with(EventType.START, "{urn:books}books", attrs=attrs) @mock.patch.object(XmlParser, "emit_event") def test_end(self, mock_emit_event): objects = [] queue = [] var = XmlVar(text=True, name="foo", qname="foo", types=[bool]) queue.append(PrimitiveNode(var, {})) result = self.parser.end(queue, objects, "enabled", "true", None) self.assertTrue(result) self.assertEqual(0, len(queue)) self.assertEqual(("enabled", True), objects[-1]) mock_emit_event.assert_called_once_with(EventType.END, "enabled", obj=result) @mock.patch.object(XmlParser, "emit_event") def test_end_with_no_result(self, mock_emit_event): objects = [] queue = [SkipNode()] result = self.parser.end(queue, "author", "foobar", None, objects) self.assertIsNone(result) self.assertEqual(0, len(objects)) self.assertEqual(0, len(queue)) self.assertEqual(0, mock_emit_event.call_count) def test_emit_event(self): mock_func = mock.Mock() self.parser.foo_bar_el = mock_func self.parser.emit_event("foo", "{tns}BarEl", a=1, b=2) mock_func.assert_called_once_with(a=1, b=2) self.assertEqual({("foo", "{tns}BarEl"): mock_func}, self.parser.emit_cache)
def setUp(self): super().setUp() self.parser = XmlParser() self.parser.objects = [(x, x) for x in "abcde"]
def setUp(self): self.parser = XmlParser() self.parser.index = 10 self.parser.objects = [(QName(x), x) for x in "abcde"]
class XmlParserTests(TestCase): def setUp(self): self.parser = XmlParser() self.parser.index = 10 self.parser.objects = [(QName(x), x) for x in "abcde"] @mock.patch.object(XmlParser, "emit_event") @mock.patch.object(XmlParser, "create_skip_queue_item") def test_queue_node_with_skip_queue_item(self, mock_create_skip_queue_item, mock_emit_event): expected_queue_item = SkipQueueItem(index=10, position=5) mock_create_skip_queue_item.return_value = expected_queue_item element = Element("{urn:books}books") last_in_queue_item = SkipQueueItem(index=0, position=0) self.parser.queue.append(last_in_queue_item) self.parser.queue_node(element) self.assertEqual(11, self.parser.index) self.assertEqual(2, len(self.parser.queue)) self.assertEqual(last_in_queue_item, self.parser.queue[0]) self.assertEqual(expected_queue_item, self.parser.queue[1]) mock_emit_event.assert_called_once_with(EventType.START, element.tag, item=last_in_queue_item, element=element) @mock.patch.object(XmlParser, "emit_event") @mock.patch.object(XmlParser, "create_skip_queue_item") def test_queue_node_with_wildcard_queue_item(self, mock_create_skip_queue_item, mock_emit_event): expected_queue_item = WildcardQueueItem(index=10, position=5, qname="foo") mock_create_skip_queue_item.return_value = expected_queue_item element = Element("{urn:books}books") last_in_queue_item = WildcardQueueItem(index=0, position=0, qname="foo") self.parser.queue.append(last_in_queue_item) self.parser.queue_node(element) self.assertEqual(11, self.parser.index) self.assertEqual(2, len(self.parser.queue)) self.assertEqual(last_in_queue_item, self.parser.queue[0]) self.assertEqual(expected_queue_item, self.parser.queue[1]) mock_emit_event.assert_called_once_with(EventType.START, element.tag, item=last_in_queue_item, element=element) @mock.patch.object(XmlParser, "emit_event") @mock.patch.object(XmlParser, "create_skip_queue_item") def test_queue_node_with_primitive_queue_item(self, mock_create_skip_queue_item, mock_emit_event): expected_queue_item = SkipQueueItem(index=10, position=5) mock_create_skip_queue_item.return_value = expected_queue_item element = Element("{urn:books}books") last_in_queue_item = PrimitiveQueueItem(index=0, position=0, types=[]) self.parser.queue.append(last_in_queue_item) self.parser.queue_node(element) self.assertEqual(11, self.parser.index) self.assertEqual(2, len(self.parser.queue)) self.assertEqual(last_in_queue_item, self.parser.queue[0]) self.assertEqual(expected_queue_item, self.parser.queue[1]) mock_emit_event.assert_called_once_with(EventType.START, element.tag, item=last_in_queue_item, element=element) @mock.patch.object(XmlParser, "emit_event") def test_queue_node_with_root(self, mock_emit_event): element = Element("{urn:books}books") root_queue_item = ClassQueueItem(index=0, position=0, meta=self.parser.class_meta(Books)) self.parser.index = 0 self.parser.queue.append(root_queue_item) self.parser.queue_node(element) self.assertEqual(1, self.parser.index) self.assertEqual(1, len(self.parser.queue)) self.assertEqual(root_queue_item, self.parser.queue[0]) mock_emit_event.assert_called_once_with(EventType.START, element.tag, item=root_queue_item, element=element) @mock.patch.object(XmlParser, "emit_event") @mock.patch.object(XmlParser, "create_wildcard_queue_item", return_value="yes") @mock.patch.object(ClassMeta, "get_var") def test_queue_node_with_wildcard_element(self, mock_get_var, mock_create_wildcard_queue_item, mock_emit_event): element = Element("{urn:books}foobar") class_queue_item = ClassQueueItem(index=0, position=0, meta=self.parser.class_meta(Books)) mock_get_var.return_value = ClassVar(qname="{urn:books}:parent", types=[], name="", tag=Tag.ANY_ELEMENT) self.parser.queue.append(class_queue_item) self.parser.queue_node(element) self.assertEqual(11, self.parser.index) self.assertEqual(2, len(self.parser.queue)) self.assertEqual(class_queue_item, self.parser.queue[0]) self.assertEqual("yes", self.parser.queue[1]) mock_create_wildcard_queue_item.assert_called_once_with( "{urn:books}:parent") mock_emit_event.assert_called_once_with(EventType.START, element.tag, item=class_queue_item, element=element) @mock.patch.object(XmlParser, "emit_event") @mock.patch.object(XmlParser, "create_class_queue_item", return_value="yes") def test_queue_node_with_dataclass_variable(self, mock_create_class_queue_item, mock_emit_event): element = Element("book") meta = self.parser.class_meta(Books) class_queue_item = ClassQueueItem(index=0, position=0, meta=meta) self.parser.queue.append(class_queue_item) self.parser.queue_node(element) self.assertEqual(11, self.parser.index) self.assertEqual(2, len(self.parser.queue)) self.assertEqual(class_queue_item, self.parser.queue[0]) self.assertEqual("yes", self.parser.queue[1]) mock_create_class_queue_item.assert_called_once_with( meta.vars[QName("book")], meta.qname) mock_emit_event.assert_called_once_with(EventType.START, element.tag, item=class_queue_item, element=element) def test_queue_node_with_unkown_element(self): element = Element("unknown") meta = self.parser.class_meta(Books) class_queue_item = ClassQueueItem(index=0, position=0, meta=meta) self.parser.queue.append(class_queue_item) with self.assertRaises(ValueError): self.parser.queue_node(element) @mock.patch.object(XmlParser, "emit_event") @mock.patch.object(XmlParser, "create_primitive_queue_item", return_value="yes") def test_queue_node_with_primitive_variable( self, mock_create_primitive_queue_item, mock_emit_event): element = Element("author") meta = self.parser.class_meta(BookForm) class_queue_item = ClassQueueItem(index=0, position=0, meta=meta) self.parser.queue.append(class_queue_item) self.parser.queue_node(element) self.assertEqual(11, self.parser.index) self.assertEqual(2, len(self.parser.queue)) self.assertEqual(class_queue_item, self.parser.queue[0]) self.assertEqual("yes", self.parser.queue[1]) mock_create_primitive_queue_item.assert_called_once_with( meta.vars["author"]) mock_emit_event.assert_called_once_with(EventType.START, element.tag, item=class_queue_item, element=element) def test_create_skip_queue_item(self): actual = self.parser.create_skip_queue_item() expected = SkipQueueItem(index=10, position=5) self.assertEqual(expected, actual) @mock.patch.object(XmlParser, "class_meta") def test_create_class_queue_item(self, mock_class_meta): mock_class_meta.return_value = "yes" class_var = ClassVar( qname="author", types=[BookForm], dataclass=True, name="", tag="", default=10, ) qname = QName("{urn}book") actual = self.parser.create_class_queue_item(class_var, qname) expected = ClassQueueItem(index=10, position=5, default=10, meta="yes") self.assertEqual(expected, actual) mock_class_meta.assert_called_once_with(BookForm, qname.namespace) def test_create_primitive_queue_item(self): class_var = ClassVar(qname="", types=[int, str], name="", tag="", default=1) actual = self.parser.create_primitive_queue_item(class_var) expected = PrimitiveQueueItem(index=10, position=5, default=1, types=[int, str]) self.assertEqual(expected, actual) def test_create_wildcard_queue_item(self): parent_qname = QName("parent") actual = self.parser.create_wildcard_queue_item(parent_qname) expected = WildcardQueueItem(index=10, position=5, qname=parent_qname) self.assertEqual(expected, actual) @mock.patch.object(XmlParser, "emit_event") def test_dequeue_node_with_skip_item(self, mock_emit_event): element = Element("author", nsmap={"foo": "bar"}) element.text = "foobar" queue_item = SkipQueueItem(index=0, position=0) self.parser.queue.append(queue_item) result = self.parser.dequeue_node(element) self.assertIsNone(result) self.assertEqual(0, len(self.parser.queue)) self.assertEqual(0, mock_emit_event.call_count) self.assertEqual({}, self.parser.namespaces.items) @mock.patch.object(XmlParser, "emit_event") @mock.patch.object(XmlParser, "parse_value", return_value="result") def test_dequeue_node_with_primitive_item(self, mock_parse_value, mock_emit_event): element = Element("author", nsmap={"prefix": "uri"}) element.text = "foobar" queue_item = PrimitiveQueueItem(index=0, position=0, types=[str], default=None) self.parser.queue.append(queue_item) result = self.parser.dequeue_node(element) self.assertEqual("result", result) self.assertEqual(0, len(self.parser.queue)) self.assertEqual((QName(element.tag), result), self.parser.objects[-1]) self.assertEqual({"prefix": "uri"}, self.parser.namespaces.ns_map) mock_parse_value.assert_called_once_with(queue_item.types, element.text, queue_item.default, element.nsmap) mock_emit_event.assert_called_once_with(EventType.END, element.tag, obj=result, element=element) @mock.patch.object(XmlParser, "emit_event") @mock.patch.object(XmlParser, "fetch_any_children", return_value=[1, 2, 3]) @mock.patch.object(XmlParser, "parse_any_element") def test_dequeue_node_with_wildcard_item(self, mock_parse_any_element, mock_fetch_any_children, mock_emit_event): obj = AnyElement() mock_parse_any_element.return_value = obj element = Element("author", nsmap={"prefix": "uri"}) queue_item = WildcardQueueItem(index=0, position=0, qname=QName("parent")) self.parser.queue.append(queue_item) result = self.parser.dequeue_node(element) self.assertEqual(obj, result) self.assertEqual(0, len(self.parser.queue)) self.assertEqual((queue_item.qname, result), self.parser.objects[-1]) self.assertEqual([1, 2, 3], result.children) self.assertEqual({"prefix": "uri"}, self.parser.namespaces.ns_map) mock_parse_any_element.assert_called_once_with(element) mock_fetch_any_children.assert_called_once_with(queue_item) mock_emit_event.assert_called_once_with(EventType.END, element.tag, obj=result, element=element) @mock.patch.object(XmlParser, "emit_event") @mock.patch.object(XmlParser, "bind_element_wild_text") @mock.patch.object(XmlParser, "bind_element_children") @mock.patch.object(XmlParser, "bind_element_text") @mock.patch.object(XmlParser, "bind_element_attrs") def test_dequeue_node_with_class_item( self, mock_bind_element_attrs, mock_bind_element_text, mock_bind_element_children, mock_bind_element_wild_text, mock_emit_event, ): def bind_element_attrs(x, y, z): x["a"] = 1 def bind_element_text(x, y, z): x["b"] = 2 def bind_element_children(x, y, z): x["c"] = 3 def bind_element_wild_text(x, y, z): x["d"] = 4 mock_bind_element_attrs.side_effect = bind_element_attrs mock_bind_element_text.side_effect = bind_element_text mock_bind_element_children.side_effect = bind_element_children mock_bind_element_wild_text.side_effect = bind_element_wild_text element = Element("author", nsmap={"prefix": "uri"}) @dataclass class Foo: a: int b: int c: int d: int meta = self.parser.class_meta(Foo) item = ClassQueueItem(index=0, position=0, meta=meta) self.parser.queue.append(item) result = self.parser.dequeue_node(element) self.assertEqual(Foo(1, 2, 3, 4), result) self.assertEqual(0, len(self.parser.queue)) self.assertEqual((QName(element.tag), result), self.parser.objects[-1]) self.assertEqual({"prefix": "uri"}, self.parser.namespaces.ns_map) mock_bind_element_attrs.assert_called_once_with( mock.ANY, meta, element) mock_bind_element_text.assert_called_once_with(mock.ANY, meta, element) mock_bind_element_children.assert_called_once_with( mock.ANY, item, element) mock_bind_element_wild_text.assert_called_once_with( mock.ANY, meta, element) mock_emit_event.assert_called_once_with(EventType.END, element.tag, obj=result, element=element) def test_dequeue_node_with_unknown_item(self): self.parser.queue.append(None) with self.assertRaises(ValueError): self.parser.dequeue_node(Element("foo")) def test_emit_event(self): mock_func = mock.Mock() self.parser.foo_bar_element = mock_func self.parser.emit_event("foo", "{tns}barElement", a=1, b=2) mock_func.assert_called_once_with(a=1, b=2) def test_fetch_any_children(self): queue_item = WildcardQueueItem(index=0, position=2, qname="foo") expected = [value for _, value in self.parser.objects[2:]] self.assertEqual(expected, self.parser.fetch_any_children(queue_item)) @mock.patch.object(XmlParser, "parse_value") def test_bind_element_attrs(self, mock_parse_value): mock_parse_value.return_value = "2020-03-02" metadata = self.parser.class_meta(ProductType) eff_date = metadata.vars["effDate"] element = Element("foo") element.set("effDate", "2020-03-01") element.set("whatever", "foo") params = dict() self.parser.bind_element_attrs(params, metadata, element) expected = { "eff_date": "2020-03-02", "other_attributes": { "whatever": "foo" } } self.assertEqual(expected, params) mock_parse_value.assert_called_once_with(eff_date.types, "2020-03-01", eff_date.default, element.nsmap) def test_bind_elements_attrs_ignore_init_false_vars(self): metadata = self.parser.class_meta(ProductType) metadata.vars["effDate"] = replace(metadata.vars["effDate"], init=False) element = Element("foo") element.set("effDate", "2020-03-01") params = dict() self.parser.bind_element_attrs(params, metadata, element) self.assertEqual({}, params) def test_bind_element_text_with_no_text_var(self): element = Element("foo") element.text = "foo" params = dict() metadata = self.parser.class_meta(Books) self.parser.bind_element_text(params, metadata, element) self.assertEqual({}, params) @mock.patch.object(XmlParser, "parse_value", return_value="yes!") def test_bind_element_text_with_text_var(self, mock_parse_value): element = Element("foo") params = dict() metadata = self.parser.class_meta(DressSize) self.parser.bind_element_text(params, metadata, element) self.assertEqual({}, params) element.text = "foo" self.parser.bind_element_text(params, metadata, element) self.assertEqual({"value": "yes!"}, params) mock_parse_value.assert_called_once_with( metadata.any_text.types, element.text, metadata.any_text.default, element.nsmap, ) def test_parse_any_element(self): comment = Comment("foo") self.assertIsNone(XmlParser.parse_any_element(comment)) element = Element("foo") element.set("a", "1") element.set("b", "2") element.set( QName(Namespace.XSI.uri, "type").text, QName(Namespace.XS.uri, "float").text) element.text = "yes" element.tail = "no" actual = XmlParser.parse_any_element(element) expected = AnyElement( qname=element.tag, text="yes", tail="no", attributes={ "a": "1", "b": "2", QName(Namespace.XSI.uri, "type"): QName(Namespace.XS.uri, "float"), }, ns_map=element.nsmap, ) self.assertEqual(expected, actual) actual = XmlParser.parse_any_element(element, False) self.assertIsNone(actual.qname) def test_element_text_and_tail(self): element = Element("foo") text, tail = XmlParser.element_text_and_tail(element) self.assertIsNone(text) self.assertIsNone(tail) element.text = " \n " element.tail = " \n " text, tail = XmlParser.element_text_and_tail(element) self.assertIsNone(text) self.assertIsNone(tail) element.text = " foo " element.tail = " bar " text, tail = XmlParser.element_text_and_tail(element) self.assertEqual("foo", text) self.assertEqual("bar", tail)
class XmlParserTests(TestCase): def setUp(self): super().setUp() self.parser = XmlParser() self.parser.index = 10 self.parser.objects = [(QName(x), x) for x in "abcde"] def test_parse_context_raises_exception(self): with self.assertRaises(ParserError) as cm: self.parser.parse_context([], Books) self.assertEqual("Failed to create target class `Books`", str(cm.exception)) def test_add_namespace(self): self.parser.add_namespace(("foo", "bar")) self.assertEqual({"foo": "bar"}, self.parser.namespaces.ns_map) @mock.patch.object(RootNode, "next_node") @mock.patch.object(XmlParser, "emit_event") def test_queue(self, mock_emit_event, mock_next_node): var = XmlText(name="foo", qname=QName("foo")) primitive_node = PrimitiveNode(position=1, var=var) mock_next_node.return_value = primitive_node element = Element("{urn:books}books") config = ParserConfig() root_queue_item = RootNode( position=0, meta=self.parser.context.build(Books), config=config, ) objects = [] queue = [] queue.append(root_queue_item) self.parser.queue(element, queue, objects) self.assertEqual(2, len(queue)) self.assertEqual(root_queue_item, queue[0]) self.assertEqual(primitive_node, queue[1]) mock_emit_event.assert_called_once_with(EventType.START, element.tag, item=root_queue_item, element=element) @mock.patch.object(XmlParser, "emit_event") @mock.patch.object(PrimitiveNode, "parse_element", return_value=("q", "result")) def test_dequeue(self, mock_parse_element, mock_emit_event): element = Element("author", nsmap={"prefix": "uri"}) element.text = "foobar" objects = [] queue = [] var = XmlText(name="foo", qname=QName("foo")) queue.append(PrimitiveNode(position=0, var=var)) result = self.parser.dequeue(element, queue, objects) self.assertEqual("result", result) self.assertEqual(0, len(queue)) self.assertEqual(("q", result), objects[-1]) mock_parse_element.assert_called_once_with(element, objects) mock_emit_event.assert_called_once_with(EventType.END, element.tag, obj=result, element=element) @mock.patch.object(XmlParser, "emit_event") def test_dequeue_with_none_qname(self, mock_emit_event): element = Element("author", nsmap={"prefix": "uri"}) element.text = "foobar" objects = [] queue = [] queue.append(SkipNode(position=0)) result = self.parser.dequeue(element, queue, objects) self.assertIsNone(result) self.assertEqual(0, len(queue)) self.assertEqual(0, len(objects)) self.assertEqual(0, mock_emit_event.call_count) def test_emit_event(self): mock_func = mock.Mock() self.parser.foo_bar_element = mock_func self.parser.emit_event("foo", "{tns}barElement", a=1, b=2) mock_func.assert_called_once_with(a=1, b=2) self.assertEqual({"{tns}barElement": "bar_element"}, self.parser.event_names)
def test_parse_from_memory_with_process_xinclude_true(self): path = fixtures_dir.joinpath("books/books-xinclude.xml") config = ParserConfig(process_xinclude=True, base_url=path.as_uri()) parser = XmlParser(config=config) actual = parser.from_bytes(path.read_bytes(), Books) self.assertEqual(self.books, actual)
def test_parse_with_process_xinclude_true(self): path = fixtures_dir.joinpath("books/books-xinclude.xml") config = ParserConfig(process_xinclude=True) parser = XmlParser(config=config) actual = parser.from_path(path, Books) self.assertEqual(self.books, actual)
def test_parse(self): path = fixtures_dir.joinpath("books/books.xml") parser = XmlParser() actual = parser.from_path(path, Books) self.assertEqual(self.books, actual) self.assertEqual({"brk": "urn:books"}, parser.namespaces.ns_map)