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 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')
Example #6
0
    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_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': {
                '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 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_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)
Example #13
0
    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')
Example #16
0
    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)
Example #17
0
 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 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 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_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)
Example #29
0
    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)
Example #30
0
    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'])
Example #33
0
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
Example #34
0
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
Example #35
0
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'))
Example #37
0
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_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_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_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))
Example #43
0
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 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'])
Example #47
0
 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)
Example #48
0
    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 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'])
Example #52
0
    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')
Example #57
0
 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')
Example #58
0
 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, '')