Source code for udapi.core.tests.test_node

#!/usr/bin/env python3
"""Unit tests for udapi.core.node."""
import io
import logging
import os
import sys
import unittest

from udapi.core.root import Root
from udapi.core.node import Node, find_minimal_common_treelet
from udapi.core.document import Document
from udapi.block.read.conllu import Conllu

logging.basicConfig(
    format='%(asctime)-15s [%(levelname)7s] %(funcName)s - %(message)s', level=logging.DEBUG)


[docs] class TestDocument(unittest.TestCase): """Unit tests for udapi.core.node."""
[docs] def test_topology(self): """Test methods/properties descendants, children, prev_node, next_node, ord.""" doc = Document() data_filename = os.path.join(os.path.dirname(__file__), 'data', 'enh_deps.conllu') doc.load_conllu(data_filename) self.assertEqual(len(doc.bundles), 1) root = doc.bundles[0].get_tree() nodes = root.descendants nodes2 = root.descendants() # descendants() and descendants should return the same sequence of nodes self.assertEqual(nodes, nodes2) self.assertEqual(len(nodes), 6) self.assertEqual(nodes[1].parent, root) self.assertEqual(nodes[2].root, root) self.assertEqual(len(nodes[1].descendants), 5) self.assertEqual(len(nodes[1].children), 3) self.assertEqual(len(nodes[1].children(add_self=True)), 4) self.assertEqual(len(nodes[1].children(add_self=1, following_only=1)), 3) self.assertEqual(nodes[2].siblings, [nodes[0], nodes[3]]) self.assertEqual(nodes[2].siblings(following_only=True), [nodes[3]]) self.assertEqual(nodes[0].next_node, nodes[1]) self.assertEqual(nodes[2].prev_node, nodes[1]) self.assertEqual(nodes[5].next_node, None) self.assertEqual(root.prev_node, None) (common_ancestor, added_nodes) = find_minimal_common_treelet(nodes[0], nodes[1]) self.assertEqual(common_ancestor, nodes[1]) self.assertEqual(list(added_nodes), []) input_nodes = [nodes[2], nodes[4], nodes[5]] (common_ancestor, added_nodes) = find_minimal_common_treelet(*input_nodes) self.assertEqual(common_ancestor, nodes[1]) self.assertEqual(list(added_nodes), [nodes[1], nodes[3]]) # ords and reorderings self.assertEqual([node.ord for node in nodes], [1, 2, 3, 4, 5, 6]) self.assertTrue(nodes[0].precedes(nodes[1])) self.assertTrue(nodes[0] < nodes[1]) self.assertFalse(nodes[0] > nodes[1]) self.assertTrue(nodes[0] <= nodes[0]) nodes[0].shift_after_node(nodes[1]) self.assertEqual([node.ord for node in nodes], [2, 1, 3, 4, 5, 6]) self.assertEqual([node.ord for node in root.descendants()], [1, 2, 3, 4, 5, 6]) self.assertEqual([node.ord for node in nodes[1].children], [2, 3, 4]) nodes[3].shift_before_node(nodes[2]) self.assertEqual([node.ord for node in nodes[1].children], [2, 3, 6])
[docs] def test_draw(self): """Test the draw() method, which uses udapi.block.write.textmodetrees.""" doc = Document() data_filename = os.path.join(os.path.dirname(__file__), 'data', 'enh_deps.conllu') doc.load_conllu(data_filename) root = doc.bundles[0].get_tree() expected1 = ("# sent_id = a-mf920901-001-p1s1A\n" "# text = Slovenská ústava: pro i proti\n" "─┮\n" " │ ╭─╼ Slovenská ADJ amod\n" " ╰─┾ ústava NOUN root\n" " ┡─╼ : PUNCT punct\n" " ╰─┮ pro ADP appos\n" " ┡─╼ i CONJ cc\n" " ╰─╼ proti ADP conj\n" "\n") expected2 = ("─┮\n" " │ ╭─╼ Slovenská Case=Nom|Degree=Pos|Gender=Fem|Negative=Pos|Number=Sing _\n" " ╰─┾ ústava Case=Nom|Gender=Fem|Negative=Pos|Number=Sing SpaceAfter=No\n" " ┡─╼ : _ _\n" " ╰─┮ pro AdpType=Prep|Case=Acc LId=pro-1\n" " ┡─╼ i _ LId=i-1\n" " ╰─╼ proti AdpType=Prep|Case=Dat LId=proti-1\n" "\n") # test non-projective tree root3 = Root() for i in range(1, 5): root3.create_child(form=str(i)) nodes = root3.descendants(add_self=1) nodes[1].parent = nodes[3] nodes[4].parent = nodes[2] expected3 = ("─┮\n" " │ ╭─╼ 1\n" " ┡─╪───┮ 2\n" " ╰─┶ 3 │\n" " ╰─╼ 4\n" "\n") try: sys.stdout = capture = io.StringIO() root.draw(color=False) self.assertEqual(capture.getvalue(), expected1) capture.seek(0) capture.truncate() root.draw(color=False, attributes='form,feats,misc', print_sent_id=False, print_text=False) self.assertEqual(capture.getvalue(), expected2) capture.seek(0) capture.truncate() root3.draw(color=False, attributes='form', print_sent_id=0, print_text=0) self.assertEqual(capture.getvalue(), expected3) finally: sys.stdout = sys.__stdout__ # pylint: disable=redefined-variable-type
[docs] def test_feats(self): """Test the morphological features.""" node = Node(root=None) self.assertEqual(str(node.feats), '_') node.feats = '' self.assertEqual(str(node.feats), '_') node.feats = None self.assertEqual(str(node.feats), '_') node.feats = {} # pylint: disable=redefined-variable-type self.assertEqual(str(node.feats), '_') node.feats = 'Mood=Ind|Person=1|Voice=Act' self.assertEqual(node.feats['Mood'], 'Ind') self.assertEqual(node.feats['Voice'], 'Act') self.assertEqual(node.feats['NonExistentFeature'], '') node.feats['Voice'] = 'Pas' self.assertEqual(str(node.feats), 'Mood=Ind|Person=1|Voice=Pas') self.assertEqual(node.feats, {'Mood': 'Ind', 'Person': '1', 'Voice': 'Pas'}) self.assertEqual(node.feats['Voice'], 'Pas') self.assertEqual(node.feats['Mood'], 'Ind') self.assertEqual(node.feats['Person'], '1') node.feats = '_' self.assertEqual(str(node.feats), '_') self.assertEqual(node.feats, {})
[docs] def test_deprel(self): """Test getting setting the dependency relation.""" node = Node(root=None, deprel='acl:relcl') self.assertEqual(node.deprel, 'acl:relcl') self.assertEqual(node.udeprel, 'acl') self.assertEqual(node.sdeprel, 'relcl') node.udeprel = 'advcl' self.assertEqual(node.deprel, 'advcl:relcl') node.sdeprel = 'tcl' self.assertEqual(node.deprel, 'advcl:tcl') node.sdeprel = '' self.assertEqual(node.deprel, 'advcl') self.assertEqual(node.udeprel, 'advcl') self.assertEqual(node.sdeprel, '') node.udeprel = 'nsubj' self.assertEqual(node.deprel, 'nsubj') self.assertEqual(node.udeprel, 'nsubj') self.assertEqual(node.sdeprel, '') node.udeprel = 'nsubj:pass:outer' self.assertEqual(node.deprel, 'nsubj:pass:outer') self.assertEqual(node.udeprel, 'nsubj') self.assertEqual(node.sdeprel, 'pass:outer')
[docs] def test_deps_getter(self): """Test enhanced dependencies.""" # Create a path to the test CoNLLU file. data_filename = os.path.join(os.path.dirname(__file__), 'data', 'enh_deps.conllu') # Read a test CoNLLU file. document = Document() reader = Conllu(files=data_filename) reader.process_document(document) # Exactly one bundle should be loaded. self.assertEqual(len(document.bundles), 1) # Obtain the dependency tree and check its sentence ID. root = document.bundles[0].get_tree() self.assertEqual(root.bundle.bundle_id, 'a-mf920901-001-p1s1A') # Check raw secondary dependencies for each node. nodes = root.descendants() self.assertEqual(nodes[0].raw_deps, '0:root|2:amod') self.assertEqual(nodes[1].raw_deps, '0:root') self.assertEqual(nodes[2].raw_deps, '0:root') self.assertEqual(nodes[3].raw_deps, '0:root') self.assertEqual(nodes[4].raw_deps, '1:amod') self.assertEqual(nodes[5].raw_deps, '5:conj') # Check deserialized dependencies. self.assertEqual(nodes[0].deps[0]['parent'], root) self.assertEqual(nodes[0].deps[0]['deprel'], 'root') self.assertEqual(nodes[5].deps[0]['parent'], nodes[4])
[docs] def test_deps_setter(self): """Test the deserialization of enhanced dependencies.""" # Create a sample dependency tree. root = Root() for _ in range(3): root.create_child() nodes = root.descendants() nodes[0].deps.append({'parent': nodes[1], 'deprel': 'test'}) self.assertEqual(nodes[0].raw_deps, '2:test')
[docs] def test_empty_nodes(self): """Test creation of empty nodes and how their ord is changed when removing nodes.""" root = Root() for i in range(3): root.create_child(form=f'node{i+1}') n1, n2, n3 = root.descendants() n3.parent = n2 e1 = n1.create_empty_child('dep', after=False, form='e1') e2 = n1.create_empty_child('dep', after=False, form='e2') e3 = n1.create_empty_child('dep', after=True, form='e3') e4 = n1.create_empty_child('dep', after=True, form='e4') e5 = n2.create_empty_child('dep', after=False, form='e5') e6 = n1.create_empty_child('dep', after=True, form='e6') self.assertEqual(root.empty_nodes, [e1, e2, e3, e4, e5, e6]) self.assertEqual(root.descendants_and_empty, [e1, e2, n1, e3, e4, e5, e6, n2, n3]) self.assertEqual([n.ord for n in root.descendants_and_empty], [0.1, 0.2, 1, 1.1, 1.2, 1.3, 1.4, 2, 3]) e5.remove() self.assertEqual(root.descendants_and_empty, [e1, e2, n1, e3, e4, e6, n2, n3]) self.assertEqual([n.ord for n in root.descendants_and_empty], [0.1, 0.2, 1, 1.1, 1.2, 1.3, 2, 3]) n1.remove() self.assertEqual(root.descendants_and_empty, [e1, e2, e3, e4, e6, n2, n3]) self.assertEqual([n.ord for n in root.descendants_and_empty], [0.1, 0.2, 0.3, 0.4, 0.5, 1, 2]) e7 = n3.create_empty_child('dep', after=True, form='e7') self.assertEqual(root.descendants_and_empty, [e1, e2, e3, e4, e6, n2, n3, e7]) self.assertEqual([n.ord for n in root.descendants_and_empty], [0.1, 0.2, 0.3, 0.4, 0.5, 1, 2, 2.1]) n2.remove() self.assertEqual(root.descendants_and_empty, [e1, e2, e3, e4, e6, e7]) self.assertEqual([n.ord for n in root.descendants_and_empty], [0.1, 0.2, 0.3, 0.4, 0.5, 0.6])
if __name__ == "__main__": unittest.main()