def test_create_empty(self): root = self.tree_with_paragraphs() reg_tree = compiler.RegulationTree(root) reg_tree.create_empty_node("205-4-a") node = find(reg_tree.tree, "205-4-a") self.assertNotEqual(None, node) self.assertEqual(node.label, ["205", "4", "a"]) self.assertEqual(node.node_type, Node.REGTEXT) node = Node(label=["205", "M2"], title="Appendix M2", node_type=Node.APPENDIX) reg_tree.add_node(node) reg_tree.create_empty_node("205-M2-1") node = find(reg_tree.tree, "205-M2-1") self.assertNotEqual(None, node) self.assertEqual(node.label, ["205", "M2", "1"]) self.assertEqual(node.node_type, Node.APPENDIX) node = Node(label=["205", Node.INTERP_MARK], title="Supplement I", node_type=Node.INTERP) reg_tree.add_node(node) reg_tree.create_empty_node("205-3-Interp") node = find(reg_tree.tree, "205-3-Interp") self.assertNotEqual(None, node) self.assertEqual(node.label, ["205", "3", Node.INTERP_MARK]) self.assertEqual(node.node_type, Node.INTERP)
def test_compile_reg_put_replace_whole_tree(self): root = self.tree_with_paragraphs() change2a = { 'action': 'PUT', 'node': { 'text': 'new text', 'label': ['205', '2', 'a'], 'node_type': 'regtext'}} change2a1 = { 'action': 'PUT', 'node': { 'text': '2a1 text', 'label': ['205', '2', 'a', '1'], 'node_type': 'regtext'}} notice_changes = { '205-2-a-1': [change2a1], '205-2-a': [change2a] } reg = compiler.compile_regulation(root, notice_changes) added_node = find(reg, '205-2-a') self.assertEqual(added_node.text, 'new text') deeper = find(reg, '205-2-a-1') self.assertEqual(deeper.text, '2a1 text')
def test_create_empty(self): root = self.tree_with_paragraphs() reg_tree = compiler.RegulationTree(root) reg_tree.create_empty_node('205-4-a') node = find(reg_tree.tree, '205-4-a') self.assertNotEqual(None, node) self.assertEqual(node.label, ['205', '4', 'a']) self.assertEqual(node.node_type, Node.REGTEXT) node = Node(label=['205', 'M2'], title='Appendix M2', node_type=Node.APPENDIX) reg_tree.add_node(node) reg_tree.create_empty_node('205-M2-1') node = find(reg_tree.tree, '205-M2-1') self.assertNotEqual(None, node) self.assertEqual(node.label, ['205', 'M2', '1']) self.assertEqual(node.node_type, Node.APPENDIX) node = Node(label=['205', Node.INTERP_MARK], title='Supplement I', node_type=Node.INTERP) reg_tree.add_node(node) reg_tree.create_empty_node('205-3-Interp') node = find(reg_tree.tree, '205-3-Interp') self.assertNotEqual(None, node) self.assertEqual(node.label, ['205', '3', Node.INTERP_MARK]) self.assertEqual(node.node_type, Node.INTERP)
def test_compile_designate(self): root = self.tree_with_subparts() change = { "action": "POST", "subpart": ["205", "Subpart", "B"], "node": Node(text="2 text", label=["205", "2"], node_type=Node.REGTEXT), } notice_changes = {"205-2": [change]} reg = compiler.compile_regulation(root, notice_changes) subpart_b = find(reg, "205-Subpart-B") self.assertEqual(len(subpart_b.children), 1) subpart_a = find(reg, "205-Subpart-A") self.assertEqual(len(subpart_a.children), 0) change = {"action": "DESIGNATE", "destination": ["205", "Subpart", "A"]} notice_changes = {"205-2": [change]} new_reg = compiler.compile_regulation(reg, notice_changes) self.assertEqual(None, find(new_reg, "205-Subpart-B")) subpart_a = find(new_reg, "205-Subpart-A") self.assertEqual(len(subpart_a.children), 1)
def move_to_subpart(self, label, subpart_label): """ Move an existing node to another subpart. If the new subpart doesn't exist, create it. """ if len(label.split('-')) != 2: logger.error( "Trying to move a non-section into a subpart: %s -> %s", label, subpart_label) return destination = find(self.tree, '-'.join(subpart_label)) if destination is None: destination = self.create_new_subpart(subpart_label) subpart_with_node = find_parent(self.tree, label) if destination and subpart_with_node: node = find(subpart_with_node, label) other_children = [c for c in subpart_with_node.children if c.label_id() != label] subpart_with_node.children = other_children destination.children = self.add_child(destination.children, node) if not subpart_with_node.children: self.delete('-'.join(subpart_with_node.label))
def test_compile_designate(self): root = self.tree_with_subparts() change = { 'action': 'POST', 'subpart': ['205', 'Subpart', 'B'], 'node': { 'text': '2 text', 'label': ['205', '2'], 'node_type': 'regtext'}} notice_changes = {'205-2': [change]} reg = compiler.compile_regulation(root, notice_changes) subpart_b = find(reg, '205-Subpart-B') self.assertEqual(len(subpart_b.children), 1) subpart_a = find(reg, '205-Subpart-A') self.assertEqual(len(subpart_a.children), 0) change = { 'action': 'DESIGNATE', 'destination': ['205', 'Subpart', 'A']} notice_changes = {'205-2': [change]} new_reg = compiler.compile_regulation(reg, notice_changes) self.assertEqual(None, find(new_reg, '205-Subpart-B')) subpart_a = find(new_reg, '205-Subpart-A') self.assertEqual(len(subpart_a.children), 1)
def test_delete_section_in_subpart(self): """Verify that we can delete a section within a subpart""" root = self.tree_with_subparts() root.children[0].children = [Node(label=['205', '12'])] reg_tree = compiler.RegulationTree(root) self.assertNotEqual(None, find(reg_tree.tree, '205-12')) reg_tree.delete('205-12') self.assertEqual(None, find(reg_tree.tree, '205-12'))
def test_compile_reg_move_wrong_reg(self): """Changes applied to other regulations shouldn't affect the regulation we care about, even if that has the same textual prefix""" root = self.tree_with_paragraphs() notice_changes = {"2055-2-a": [{"action": "MOVE", "destination": ["2055", "2", "b"]}]} reg = compiler.compile_regulation(root, notice_changes) self.assertEqual(find(reg, "205-2-a").text, "n2a") self.assertEqual(find(reg, "205-2-b").text, "n2b") self.assertEqual(find(reg, "2055-2-b"), None)
def test_delete_section_in_subpart(self): """Verify that we can delete a section within a subpart""" root = self._tree_with_subparts() root.children[0].children = [Node(label=['205', '12'])] reg_tree = compiler.RegulationTree(root) self.assertNotEqual(None, find(reg_tree.tree, '205-12')) reg_tree.delete('205-12') self.assertEqual(None, find(reg_tree.tree, '205-12'))
def test_compile_reg_move_wrong_reg(self): """Changes applied to other regulations shouldn't affect the regulation we care about, even if that has the same textual prefix""" root = self.tree_with_paragraphs() notice_changes = {'2055-2-a': [{'action': 'MOVE', 'destination': ['2055', '2', 'b']}]} reg = compiler.compile_regulation(root, notice_changes) self.assertEqual(find(reg, '205-2-a').text, 'n2a') self.assertEqual(find(reg, '205-2-b').text, 'n2b') self.assertEqual(find(reg, '2055-2-b'), None)
def test_delete(self): root = self.tree_with_paragraphs() reg_tree = compiler.RegulationTree(root) self.assertNotEqual(None, find(reg_tree.tree, '205-2-a')) reg_tree.delete('205-2-a') self.assertEqual(None, find(reg_tree.tree, '205-2-a')) # Verify this doesn't cause an error reg_tree.delete('205-2-a')
def add_section(self, node, subpart_label): """ Add a new section to a subpart. """ existing = find(self.tree, node.label_id()) if existing and is_reserved_node(existing): logging.warning('Replacing reserved node: {0}'.format(node.label_id())) self.replace_node_and_subtree(node) else: subpart = find(self.tree, '-'.join(subpart_label)) subpart.children = self.add_child(subpart.children, node)
def test_replace_node_heading(self): root = self.tree_with_paragraphs() n2a = find(root, '205-2-a') n2a.text = 'Previous keyterm. Remainder.' reg_tree = compiler.RegulationTree(root) change = {'node': {'text': 'Replaced.'}} reg_tree.replace_node_heading('205-2-a', change) changed_node = find(reg_tree.tree, '205-2-a') self.assertEqual(changed_node.text, 'Replaced. Remainder.')
def add_section(self, node, subpart_label): """ Add a new section to a subpart. """ existing = find(self.tree, node.label_id()) if existing and is_reserved_node(existing): logging.warning('Replacing reserved node: {0}'.format( node.label_id())) self.replace_node_and_subtree(node) else: subpart = find(self.tree, '-'.join(subpart_label)) subpart.children = self.add_child(subpart.children, node)
def test_replace_node_heading(self): root = self.tree_with_paragraphs() n2a = find(root, "205-2-a") n2a.text = "Previous keyterm. Remainder." reg_tree = compiler.RegulationTree(root) change = {"node": Node(text="Replaced.")} reg_tree.replace_node_heading("205-2-a", change) changed_node = find(reg_tree.tree, "205-2-a") self.assertEqual(changed_node.text, "Replaced. Remainder.")
def test_move_to_subpart(self): sect5, sect7 = Node(label=["111", "5"]), Node(label=["111", "7"]) sub_a = Node(label=["111", "Subpart", "A"], node_type=Node.SUBPART, children=[sect5]) sub_b = Node(label=["111", "Subpart", "B"], node_type=Node.SUBPART, children=[sect7]) root = Node(children=[sub_a, sub_b], label=["111"]) tree = compiler.RegulationTree(root) tree.move_to_subpart("111-5", sub_b.label) sub_b = find(tree.tree, "111-Subpart-B") sect5, sect7 = find(tree.tree, "111-5"), find(tree.tree, "111-7") self.assertEqual([sub_b], tree.tree.children) self.assertEqual([sect5, sect7], sub_b.children)
def test_reserve_existing(self): root = self.tree_with_paragraphs() reg_tree = compiler.RegulationTree(root) before_reserve = find(reg_tree.tree, '205-2-a') self.assertNotEqual(before_reserve.text, '[Reserved]') n2 = Node('[Reserved]', label=['205', '2']) reg_tree.reserve('205-2', n2) after_reserve = find(reg_tree.tree, '205-2') self.assertEqual(after_reserve.text, '[Reserved]') reserve_child = find(reg_tree.tree, '205-2-a') self.assertEqual(None, reserve_child)
def test_move_to_subpart(self): sect5, sect7 = Node(label=['111', '5']), Node(label=['111', '7']) sub_a = Node(label=['111', 'Subpart', 'A'], node_type=Node.SUBPART, children=[sect5]) sub_b = Node(label=['111', 'Subpart', 'B'], node_type=Node.SUBPART, children=[sect7]) root = Node(children=[sub_a, sub_b], label=['111']) tree = compiler.RegulationTree(root) tree.move_to_subpart('111-5', sub_b.label) sub_b = find(tree.tree, '111-Subpart-B') sect5, sect7 = find(tree.tree, '111-5'), find(tree.tree, '111-7') self.assertEqual([sub_b], tree.tree.children) self.assertEqual([sect5, sect7], sub_b.children)
def test_reserve_existing(self): root = self.tree_with_paragraphs() reg_tree = compiler.RegulationTree(root) before_reserve = find(reg_tree.tree, "205-2-a") self.assertNotEqual(before_reserve.text, "[Reserved]") n2 = Node("[Reserved]", label=["205", "2"]) reg_tree.reserve("205-2", n2) after_reserve = find(reg_tree.tree, "205-2") self.assertEqual(after_reserve.text, "[Reserved]") reserve_child = find(reg_tree.tree, "205-2-a") self.assertEqual(None, reserve_child)
def test_compile_reg_keep_root(self): root = self.tree_with_paragraphs() change2 = { 'action': 'KEEP', 'node': { 'text': '* * *', 'label': ['205', '2'], 'node_type': 'regtext' } } change2a = { 'action': 'PUT', 'node': { 'text': '(a) A Test', 'label': ['205', '2', 'a'], 'node_type': 'regtext' } } notice_changes = {'205-2': [change2], '205-2-a': [change2a]} reg = compiler.compile_regulation(root, notice_changes) changed = find(reg, '205-2') self.assertEqual(changed.text, 'n2') # text didn't change self.assertEqual(2, len(changed.children)) changed2a, changed2b = changed.children self.assertEqual(['205', '2', 'a'], changed2a.label) self.assertEqual('(a) A Test', changed2a.text) self.assertEqual([], changed2a.children) self.assertEqual(['205', '2', 'b'], changed2b.label)
def test_add_node_reserved_appendix(self): reserved_node = Node('', label=['205', 'R'], node_type=Node.APPENDIX, title='Appendix R-[Reserved]') root = Node('', label=['205'], children=[reserved_node]) reg_tree = compiler.RegulationTree(root) new_node = Node('', label=['205', 'R'], node_type=Node.APPENDIX, title="Appendix R-Revision'd", children=[ Node('R1', label=['205', 'R', '1'], node_type=Node.APPENDIX), Node('R2', label=['205', 'R', '2'], node_type=Node.APPENDIX) ]) reg_tree.add_node(new_node) added_node = find(reg_tree.tree, '205-R') self.assertEqual(2, len(added_node.children)) self.assertEqual("Appendix R-Revision'd", added_node.title)
def test_add_node_reserved(self): root = self.tree_with_paragraphs() reserved_node = Node("[Reserved]", label=["205", "2", "a", "1"]) n2a = find(root, "205-2-a") n2a.children = [reserved_node] reg_tree = compiler.RegulationTree(root) parent = find(reg_tree.tree, "205-2-a") self.assertEqual(len(parent.children), 1) new_node = Node("(i) new content", label=["205", "2", "a", "1"]) reg_tree.add_node(new_node) added_node = find(reg_tree.tree, "205-2-a-1") self.assertEqual(added_node.text, "(i) new content") self.assertEqual(len(parent.children), 1)
def test_get_parent(self): root = self.tree_with_paragraphs() reg_tree = compiler.RegulationTree(root) node = find(reg_tree.tree, '205-2-a') parent = reg_tree.get_parent(node) self.assertEqual(parent.label, ['205', '2'])
def match_labels_and_changes(amendments, section_node): """ Given the list of amendments, and the parsed section node, match the two so that we're only changing what's been flagged as changing. This helps eliminate paragraphs that are just stars for positioning, for example. """ amended_labels = [a.label_id() for a in amendments] amend_map = OrderedDict() for amend in amendments: existing = amend_map.get(amend.label_id(), []) change = {'action': amend.action, 'amdpar_xml': amend.amdpar_xml} if amend.field is not None: change['field'] = amend.field if amend.action == 'MOVE': change['destination'] = amend.destination amend_map[amend.label_id()] = existing + [change] elif amend.action == 'DELETE': amend_map[amend.label_id()] = existing + [change] elif section_node is not None: node = struct.find(section_node, amend.label_id()) if node is None: candidate = find_misparsed_node(section_node, amend.label, change, amended_labels) if candidate: amend_map[amend.label_id()] = existing + [candidate] else: change['node'] = node change['candidate'] = False level2 = amend.tree_format_level2() if level2 and node.is_section(): change['parent_label'] = level2 amend_map[amend.label_id()] = existing + [change] resolve_candidates(amend_map) return amend_map
def create_add_amendment(amendment): """ An amendment comes in with a whole tree structure. We break apart the tree here (this is what flatten does), convert the Node objects to JSON representations. This ensures that each amendment only acts on one node. In addition, this futzes with the change's field when stars are present. """ nodes_list = [] flatten_tree(nodes_list, amendment['node']) changes = [format_node(n, amendment) for n in nodes_list] for change in filter(lambda c: c.values()[0]['action'] == 'PUT', changes): label = change.keys()[0] node = struct.find(amendment['node'], label) text = node.text.strip() marker = marker_of(node) text = text[len(marker):].strip() # Text is stars, but this is not the root. Explicitly try to keep # this node if text == '* * *': change[label]['action'] = 'KEEP' # If text ends with a colon and is followed by stars, assume we are # only modifying the intro text if (text[-1:] == ':' and node.label == amendment['node'].label and node.source_xml is not None): following = node.source_xml.getnext() if following is not None and following.tag == 'STARS': change[label]['field'] = '[text]' return changes
def create_add_amendment(amendment): """ An amendment comes in with a whole tree structure. We break apart the tree here (this is what flatten does), convert the Node objects to JSON representations. This ensures that each amendment only acts on one node. In addition, this futzes with the change's field when stars are present. """ nodes_list = [] flatten_tree(nodes_list, amendment['node']) changes = [format_node(n, amendment) for n in nodes_list] for change in filter(lambda c: c.values()[0]['action'] == 'PUT', changes): label = change.keys()[0] node = struct.find(amendment['node'], label) text = node.text.strip() marker = marker_of(node) text = text[len(marker):].strip() # Text is stars, but this is not the root. Explicitly try to keep # this node if text == '* * *': change[label]['action'] = Verb.KEEP # If text ends with a colon and is followed by stars, assume we are # only modifying the intro text if (text[-1:] == ':' and node.label == amendment['node'].label and node.source_xml is not None): following = node.source_xml.getnext() if following is not None and following.tag == 'STARS': change[label]['field'] = '[text]' return changes
def test_replace_node_and_subtree(self): n1 = Node('n1', label=['205', '1']) n2 = Node('n2', label=['205', '2']) n4 = Node('n4', label=['205', '4']) n2a = Node('n2a', label=['205', '2', 'a']) n2b = Node('n2b', label=['205', '2', 'b']) n2.children = [n2a, n2b] root = Node('', label=['205']) root.children = [n1, n2, n4] reg_tree = compiler.RegulationTree(root) a2 = Node('a2', label=['205', '2']) a2e = Node('a2e', label=['205', '2', 'e']) a2f = Node('a2f', label=['205', '2', 'f']) a2.children = [a2e, a2f] reg_tree.replace_node_and_subtree(a2) new_tree = Node('', label=[205]) new_tree.children = [n1, a2, n4] self.assertEqual(new_tree, reg_tree.tree) self.assertEqual(None, find(reg_tree.tree, '205-2-a'))
def match_labels_and_changes(amendments, section_node): """ Given the list of amendments, and the parsed section node, match the two so that we're only changing what's been flagged as changing. This helps eliminate paragraphs that are just stars for positioning, for example. """ amended_labels = [a.label_id() for a in amendments] amend_map = defaultdict(list) for amend in amendments: change = {'action': amend.action} if amend.field is not None: change['field'] = amend.field if amend.action == 'MOVE': change['destination'] = amend.destination amend_map[amend.label_id()].append(change) elif amend.action == 'DELETE': amend_map[amend.label_id()].append(change) elif section_node is not None: node = struct.find(section_node, amend.label_id()) if node is None: candidate = find_misparsed_node(section_node, amend.label, change, amended_labels) if candidate: amend_map[amend.label_id()].append(candidate) else: change['node'] = node change['candidate'] = False amend_map[amend.label_id()].append(change) resolve_candidates(amend_map) return amend_map
def test_add_node_reserved(self): root = self.tree_with_paragraphs() reserved_node = Node('[Reserved]', label=['205', '2', 'a', '1']) n2a = find(root, '205-2-a') n2a.children = [reserved_node] reg_tree = compiler.RegulationTree(root) parent = find(reg_tree.tree, '205-2-a') self.assertEqual(len(parent.children), 1) new_node = Node('(i) new content', label=['205', '2', 'a', '1']) reg_tree.add_node(new_node) added_node = find(reg_tree.tree, '205-2-a-1') self.assertEqual(added_node.text, '(i) new content') self.assertEqual(len(parent.children), 1)
def test_replace_node_and_subtree(self): n1 = Node("n1", label=["205", "1"]) n2 = Node("n2", label=["205", "2"]) n4 = Node("n4", label=["205", "4"]) n2a = Node("n2a", label=["205", "2", "a"]) n2b = Node("n2b", label=["205", "2", "b"]) n2.children = [n2a, n2b] root = Node("", label=["205"]) root.children = [n1, n2, n4] reg_tree = compiler.RegulationTree(root) a2 = Node("a2", label=["205", "2"]) a2e = Node("a2e", label=["205", "2", "e"]) a2f = Node("a2f", label=["205", "2", "f"]) a2.children = [a2e, a2f] reg_tree.replace_node_and_subtree(a2) new_tree = Node("", label=[205]) new_tree.children = [n1, a2, n4] self.assertEqual(new_tree, reg_tree.tree) self.assertEqual(None, find(reg_tree.tree, "205-2-a"))
def test_add_node_placeholder(self): node = Node(label=["1234", "2", "b", "1", Node.INTERP_MARK, "1"], text="1. Some Content", node_type=Node.INTERP) node = Node( label=["1234", "2", "b", "1", Node.INTERP_MARK], title="Paragraph 2(b)(1)", node_type=Node.INTERP, children=[node], ) # This is the placeholder node = Node(label=["1234", "2", "b", Node.INTERP_MARK], node_type=Node.INTERP, children=[node]) node = Node(label=["1234", "2", Node.INTERP_MARK], node_type=Node.INTERP, children=[node]) root = Node( label=["1234"], node_type=Node.REGTEXT, children=[Node(label=["1234", Node.INTERP_MARK], title="Supplement I", children=[node])], ) reg_tree = compiler.RegulationTree(root) node = Node(label=["1234", "2", "b", Node.INTERP_MARK], title="2(b) Some Header", node_type=Node.INTERP) reg_tree.add_node(node) i2 = find(reg_tree.tree, "1234-2-Interp") self.assertEqual(1, len(i2.children)) i2b = i2.children[0] self.assertEqual("2(b) Some Header", i2b.title) self.assertEqual(1, len(i2b.children)) i2b1 = i2b.children[0] self.assertEqual("Paragraph 2(b)(1)", i2b1.title) self.assertEqual(1, len(i2b1.children)) i2b11 = i2b1.children[0] self.assertEqual("1. Some Content", i2b11.text) self.assertEqual(0, len(i2b11.children))
def match_labels_and_changes(amendments, section_node): """ Given the list of amendments, and the parsed section node, match the two so that we're only changing what's been flagged as changing. This helps eliminate paragraphs that are just stars for positioning, for example. """ amended_labels = [a.label_id() for a in amendments] amend_map = defaultdict(list) for amend in amendments: change = {'action': amend.action} if amend.field is not None: change['field'] = amend.field if amend.action == 'MOVE': change['destination'] = amend.destination amend_map[amend.label_id()].append(change) elif amend.action == 'DELETE': amend_map[amend.label_id()].append(change) elif section_node is not None: node = struct.find(section_node, amend.label_id()) if node is None: candidate = find_misparsed_node( section_node, amend.label, change, amended_labels) if candidate: amend_map[amend.label_id()].append(candidate) else: change['node'] = node change['candidate'] = False level2 = amend.tree_format_level2() if level2 and node.is_section(): change['parent_label'] = level2 amend_map[amend.label_id()].append(change) resolve_candidates(amend_map) return amend_map
def get_parent(self, node): """ Get the parent of a node. Returns None if parent not found. """ parent = find_parent(self.tree, node) if not parent: # e.g. because the node doesn't exist in the tree yet parent_label_id = get_parent_label(node) parent = find(self.tree, parent_label_id) return parent
def delete(self, label_id): """ Delete the node with label_id from the tree. """ node = find(self.tree, label_id) if node is None: logger.warning("Attempting to delete %s failed", label_id) else: self.delete_from_parent(node)
def move_to_subpart(self, label, subpart_label): """ Move an existing node to another subpart. If the new subpart doesn't exist, create it. """ destination = find(self.tree, '-'.join(subpart_label)) if destination is None: destination = self.create_new_subpart(subpart_label) subpart_with_node = self.get_subpart_for_node(label) if destination and subpart_with_node: node = find(subpart_with_node, label) other_children = [c for c in subpart_with_node.children if c.label_id() != label] subpart_with_node.children = other_children destination.children = self.add_child(destination.children, node)
def move(self, origin, destination): """ Move a node from one part in the tree to another. """ origin = find(self.tree, origin) self.delete_from_parent(origin) origin = overwrite_marker(origin, destination[-1]) origin.label = destination self.add_node(origin)
def replace_node_heading(self, label, change): """ A node's heading is it's keyterm. We handle this here, but not well, I think. """ node = find(self.tree, label) node.text = replace_first_sentence(node.text, change['node']['text']) if hasattr(node, 'tagged_text') and 'tagged_text' in change['node']: node.tagged_text = replace_first_sentence( node.tagged_text, change['node']['tagged_text'])
def replace_node_heading(self, label, change): """ A node's heading is it's keyterm. We handle this here, but not well, I think. """ node = find(self.tree, label) node.text = replace_first_sentence(node.text, change['node']['text']) if node.tagged_text and 'tagged_text' in change['node']: node.tagged_text = replace_first_sentence( node.tagged_text, change['node']['tagged_text'])
def test_reserve_add_new(self): root = self.tree_with_paragraphs() reg_tree = compiler.RegulationTree(root) n2ai = Node('[Reserved]', label=['205', '2', 'a', '1']) reg_tree.reserve('205-2-a-1', n2ai) self.assertNotEqual(reg_tree.tree, root) reserved_node = find(reg_tree.tree, '205-2-a-1') self.assertEqual(reserved_node.text, '[Reserved]')
def test_replace_node_title(self): root = self.tree_with_paragraphs() change = {'node': {'title': 'new title'}} reg_tree = compiler.RegulationTree(root) reg_tree.replace_node_title('205-2-a', change) changed_node = find(reg_tree.tree, '205-2-a') self.assertEqual(changed_node.title, 'new title')
def test_get_section_parent(self): root = self.tree_with_subparts() section = Node('section', label=['205', '3'], node_type=Node.REGTEXT) subpart = find(root, '205-Subpart-B') subpart.children = [section] reg_tree = compiler.RegulationTree(root) parent = reg_tree.get_section_parent(section) self.assertEqual(parent.label_id(), '205-Subpart-B')
def test_get_subpart_for_node(self): root = self.tree_with_subparts() n1 = Node('n1', label=['205', '1']) nsb = find(root, '205-Subpart-B') nsb.children = [n1] reg_tree = compiler.RegulationTree(root) subpart = reg_tree.get_subpart_for_node('205-1') self.assertEqual(subpart.label_id(), '205-Subpart-B')
def test_compile_reg_move_wrong_reg(self): root = self.tree_with_paragraphs() notice_changes = { '202-2-a': [{ 'action': 'MOVE', 'destination': ['202', '2', 'b'] }] } reg = compiler.compile_regulation(root, notice_changes) self.assertEqual(find(reg, '205-2-a').text, 'n2a')
def get_parent(self, node): """ Get the parent of a node. Returns None if parent not found. """ parent = find_parent(self.tree, node) if not parent: # e.g. because the node doesn't exist in the tree yet parent_label_id = get_parent_label(node) parent = find(self.tree, parent_label_id) if not parent: logger.error("Could not find parent of %s. Misparsed amendment?", node.label_id()) return parent
def replace_node_heading(self, label, change): """ A node's heading is it's keyterm. We handle this here, but not well, I think. """ node = find(self.tree, label) node.text = replace_first_sentence(node.text, change['node'].text) if (hasattr(node, 'tagged_text') and change['node'].tagged_text is not None): node.tagged_text = replace_first_sentence( node.tagged_text, change['node'].tagged_text)
def test_add_node_no_parent(self): root = self.tree_with_paragraphs() reg_tree = compiler.RegulationTree(root) node = Node('', label=['205', '3', 'a'], node_type=Node.REGTEXT) reg_tree.add_node(node) parent = find(reg_tree.tree, '205-3') self.assertNotEqual(None, parent) self.assertEqual(parent.text, '')