def test_should_recursively_call_itself_on_dependencies_before_adding_dependencies_to_graph(
        self, mock_add_location_dependencies, mock_generate_cell_subgraph
    ):
        mock_generate_cell_subgraph.copied_call_args_list = []

        def mock_recalc_recursive_call(worksheet, context, loc, visited, path):
            self.assertFalse(mock_add_location_dependencies.called)
            mock_generate_cell_subgraph.copied_call_args_list.append((worksheet, context, loc, set(visited), list(path)))


        mock_generate_cell_subgraph.side_effect = mock_recalc_recursive_call
        mock_generate_cell_subgraph_was_called_before_add_location_dependencies = []

        def add_location_dependencies_side_effect(*_):
            mock_generate_cell_subgraph_was_called_before_add_location_dependencies.append(mock_generate_cell_subgraph.called)
        mock_add_location_dependencies.side_effect = add_location_dependencies_side_effect

        worksheet = Worksheet()
        worksheet[1, 11].formula = '=formula'
        worksheet[1, 11].dependencies = [(2, 22), (3, 33)]
        context = sentinel.context

        _generate_cell_subgraph(worksheet, context, (1, 11), set(), [])

        self.assertTrue(mock_add_location_dependencies.called)
        self.assertTrue(mock_generate_cell_subgraph_was_called_before_add_location_dependencies[0])
        self.assertItemsEqual(
            mock_generate_cell_subgraph.copied_call_args_list,
            [
                (worksheet, context, (2, 22), set(), [(1, 11)]),
                (worksheet, context, (3, 33), set(), [(1, 11)]),
            ]
        )
示例#2
0
    def test_should_recursively_call_itself_on_dependencies_before_adding_dependencies_to_graph(
            self, mock_add_location_dependencies, mock_generate_cell_subgraph):
        mock_generate_cell_subgraph.copied_call_args_list = []

        def mock_recalc_recursive_call(worksheet, context, loc, visited, path):
            self.assertFalse(mock_add_location_dependencies.called)
            mock_generate_cell_subgraph.copied_call_args_list.append(
                (worksheet, context, loc, set(visited), list(path)))

        mock_generate_cell_subgraph.side_effect = mock_recalc_recursive_call
        mock_generate_cell_subgraph_was_called_before_add_location_dependencies = []

        def add_location_dependencies_side_effect(*_):
            mock_generate_cell_subgraph_was_called_before_add_location_dependencies.append(
                mock_generate_cell_subgraph.called)

        mock_add_location_dependencies.side_effect = add_location_dependencies_side_effect

        worksheet = Worksheet()
        worksheet[1, 11].formula = '=formula'
        worksheet[1, 11].dependencies = [(2, 22), (3, 33)]
        context = sentinel.context

        _generate_cell_subgraph(worksheet, context, (1, 11), set(), [])

        self.assertTrue(mock_add_location_dependencies.called)
        self.assertTrue(
            mock_generate_cell_subgraph_was_called_before_add_location_dependencies[
                0])
        self.assertItemsEqual(
            mock_generate_cell_subgraph.copied_call_args_list, [
                (worksheet, context, (2, 22), set(), [(1, 11)]),
                (worksheet, context, (3, 33), set(), [(1, 11)]),
            ])
    def test_should_not_reraise_cycle_error_if_its_outside_the_cycle_path(
        self, mock_report_cell_error, mock_recursive_call
    ):
        cycle_error = CycleError([(1, 2), (3, 4), (1, 2)])
        worksheet = Worksheet()
        worksheet[1, 3].formula = "=foo"
        mock_recursive_call.side_effect = die(cycle_error)

        _generate_cell_subgraph(worksheet, sentinel.graph, (1, 3), set(), []) # should not raise
    def test_should_raise_any_existing_cycle_error_for_visited_locations(self):
        cycle_error = CycleError([(1, 2), (3, 4), (1, 2)])
        worksheet = Worksheet()
        worksheet[1, 2].error = cycle_error

        try:
            _generate_cell_subgraph(worksheet, sentinel.graph, (1, 2), set([(1, 2)]), sentinel.path)
        except Exception, e:
            self.assertEquals(e, cycle_error)
    def test_should_add_cell_to_graph_if_formula_not_set_but_python_formula_is(
        self, mock_add_location_dependencies
    ):
        worksheet = Worksheet()
        worksheet[1, 2].python_formula = 'blerk'

        _generate_cell_subgraph(worksheet, sentinel.graph, (1, 2), set(), [])

        self.assertCalledOnce(mock_add_location_dependencies, sentinel.graph, (1, 2), set())
示例#6
0
    def test_should_add_cell_to_graph_if_formula_not_set_but_python_formula_is(
            self, mock_add_location_dependencies):
        worksheet = Worksheet()
        worksheet[1, 2].python_formula = 'blerk'

        _generate_cell_subgraph(worksheet, sentinel.graph, (1, 2), set(), [])

        self.assertCalledOnce(mock_add_location_dependencies, sentinel.graph,
                              (1, 2), set())
示例#7
0
    def test_should_not_reraise_cycle_error_if_its_outside_the_cycle_path(
            self, mock_report_cell_error, mock_recursive_call):
        cycle_error = CycleError([(1, 2), (3, 4), (1, 2)])
        worksheet = Worksheet()
        worksheet[1, 3].formula = "=foo"
        mock_recursive_call.side_effect = die(cycle_error)

        _generate_cell_subgraph(worksheet, sentinel.graph, (1, 3), set(),
                                [])  # should not raise
示例#8
0
    def test_should_raise_any_existing_cycle_error_for_visited_locations(self):
        cycle_error = CycleError([(1, 2), (3, 4), (1, 2)])
        worksheet = Worksheet()
        worksheet[1, 2].error = cycle_error

        try:
            _generate_cell_subgraph(worksheet, sentinel.graph, (1, 2),
                                    set([(1, 2)]), sentinel.path)
        except Exception, e:
            self.assertEquals(e, cycle_error)
示例#9
0
    def test_should_not_reprocess_locations_already_in_visited_even_if_it_is_in_worksheet(
            self, mock_add_location_dependencies):
        cell = Cell()
        cell.formula = 'constant'
        worksheet = Worksheet()
        worksheet[1, 2] = cell

        _generate_cell_subgraph(worksheet, sentinel.graph, (1, 2),
                                set([(1, 2)]), [])

        self.assertFalse(mock_add_location_dependencies.called)
    def test_should_not_reprocess_locations_already_in_visited_even_if_it_is_in_worksheet(
        self, mock_add_location_dependencies
    ):
        cell = Cell()
        cell.formula = 'constant'
        worksheet = Worksheet()
        worksheet[1, 2] = cell

        _generate_cell_subgraph(worksheet, sentinel.graph, (1, 2), set([(1, 2)]), [])

        self.assertFalse(mock_add_location_dependencies.called)
    def test_should_report_cell_error_and_not_add_location_on_recursive_call_raising_cycle_error_if_location_is_not_in_cycle_path(
        self, mock_report_cell_error, mock_add_location_dependencies
    ):
        worksheet = Worksheet()
        worksheet[1, 11].formula = '=A12'
        worksheet[1, 11].dependencies = [(1, 12)]

        _generate_cell_subgraph(worksheet, sentinel.graph, (1, 11), set(), [])

        self.assertCalledOnce(mock_add_location_dependencies, sentinel.graph, (1, 11), set())
        self.assertCalledOnce(mock_report_cell_error, worksheet, (1, 11), CycleError([]))
    def test_reports_error_once_per_cell(self, mock_report_cell_error):
        mock_report_cell_error.side_effect = report_cell_error
        worksheet = Worksheet()
        worksheet[1, 1].formula = '=A2'
        worksheet[1, 2].formula = '=A1'

        try:
            _generate_cell_subgraph(worksheet, {}, (1, 1), set(), [])
        except CycleError:
            pass

        self.assertEquals(len(mock_report_cell_error.call_args_list), 2)
    def test_does_not_include_discovered_cycle_in_deps_of_current_cell(self):#
        worksheet = Worksheet()
        worksheet[1, 1].formula = '=A2'
        worksheet[1, 2].formula = '=A1'
        worksheet[1, 3].formula = '=A1'

        visited = set()
        graph = {}

        _generate_cell_subgraph(worksheet, graph, (1, 3), visited, [])
        self.assertEquals(graph, {(1, 3): Node((1, 3), set())})
        self.assertEquals(visited, set([(1, 2), (1, 3), (1, 1)]))
示例#14
0
    def test_should_report_then_raise_cycle_error_when_there_is_a_cycle(
            self, mock_report_cell_error):
        cycle_error = CycleError([(1, 2), (3, 4), (1, 2)])
        worksheet = Worksheet()
        worksheet[1, 2].formula = "=foo"

        visited = set()
        try:
            _generate_cell_subgraph(worksheet, sentinel.graph, (1, 2), visited,
                                    [(8, 9), (1, 2), (3, 4)])
        except Exception, e:
            self.assertEquals(e, cycle_error)
示例#15
0
    def test_reports_error_once_per_cell(self, mock_report_cell_error):
        mock_report_cell_error.side_effect = report_cell_error
        worksheet = Worksheet()
        worksheet[1, 1].formula = '=A2'
        worksheet[1, 2].formula = '=A1'

        try:
            _generate_cell_subgraph(worksheet, {}, (1, 1), set(), [])
        except CycleError:
            pass

        self.assertEquals(len(mock_report_cell_error.call_args_list), 2)
示例#16
0
    def test_should_report_cell_error_and_not_add_location_on_recursive_call_raising_cycle_error_if_location_is_not_in_cycle_path(
            self, mock_report_cell_error, mock_add_location_dependencies):
        worksheet = Worksheet()
        worksheet[1, 11].formula = '=A12'
        worksheet[1, 11].dependencies = [(1, 12)]

        _generate_cell_subgraph(worksheet, sentinel.graph, (1, 11), set(), [])

        self.assertCalledOnce(mock_add_location_dependencies, sentinel.graph,
                              (1, 11), set())
        self.assertCalledOnce(mock_report_cell_error, worksheet, (1, 11),
                              CycleError([]))
    def test_should_report_then_raise_cycle_error_when_there_is_a_cycle(
        self, mock_report_cell_error
    ):
        cycle_error = CycleError([(1, 2), (3, 4), (1, 2)])
        worksheet = Worksheet()
        worksheet[1, 2].formula = "=foo"

        visited = set()
        try:
            _generate_cell_subgraph(worksheet, sentinel.graph, (1, 2), visited, [(8, 9), (1, 2), (3, 4)])
        except Exception, e:
            self.assertEquals(e, cycle_error)
示例#18
0
    def test_does_not_include_discovered_cycle_in_deps_of_current_cell(
            self):  #
        worksheet = Worksheet()
        worksheet[1, 1].formula = '=A2'
        worksheet[1, 2].formula = '=A1'
        worksheet[1, 3].formula = '=A1'

        visited = set()
        graph = {}

        _generate_cell_subgraph(worksheet, graph, (1, 3), visited, [])
        self.assertEquals(graph, {(1, 3): Node((1, 3), set())})
        self.assertEquals(visited, set([(1, 2), (1, 3), (1, 1)]))
    def test_should_reraise_cycle_error_after_reporting_if_its_in_the_cycle_path(
        self, mock_report_cell_error, mock_recursive_call
    ):
        cycle_error = CycleError([(1, 2), (3, 4), (1, 2)])
        worksheet = Worksheet()
        worksheet[1, 2].formula = "=C4"
        mock_recursive_call.side_effect = die(cycle_error)

        visited = set()
        try:
            _generate_cell_subgraph(worksheet, sentinel.graph, (1, 2), visited, [])
        except Exception, e:
            self.assertEquals(e, cycle_error)
示例#20
0
    def test_should_reraise_cycle_error_after_reporting_if_its_in_the_cycle_path(
            self, mock_report_cell_error, mock_recursive_call):
        cycle_error = CycleError([(1, 2), (3, 4), (1, 2)])
        worksheet = Worksheet()
        worksheet[1, 2].formula = "=C4"
        mock_recursive_call.side_effect = die(cycle_error)

        visited = set()
        try:
            _generate_cell_subgraph(worksheet, sentinel.graph, (1, 2), visited,
                                    [])
        except Exception, e:
            self.assertEquals(e, cycle_error)
示例#21
0
    def test_should_add_dependencies_to_graph(self,
                                              mock_add_location_dependencies):
        worksheet = Worksheet()
        worksheet[99, 98].formula = '=foobar'
        worksheet[1, 11].formula = '=foo'
        worksheet[1, 11].dependencies = [(99, 98)]
        graph = sentinel.graph

        _generate_cell_subgraph(worksheet, graph, (1, 11), set(), [])

        self.assertEqual(
            mock_add_location_dependencies.call_args,
            ((graph, (1, 11), set([(99, 98)])), {}),
        )
示例#22
0
    def test_should_remove_dependencies_with_errors_and_empty_cells(
            self, mock_add_location_dependencies):
        worksheet = Worksheet()
        worksheet[1, 1].formula = '1'
        worksheet[1, 2].error = CycleError([])
        worksheet[1, 3].error = SyntaxError('')
        worksheet[1, 11].formula = '=foo'
        worksheet[1, 11].dependencies = [(1, 1), (1, 2), (1, 3), (1, 4)]
        graph = sentinel.graph

        _generate_cell_subgraph(worksheet, graph, (1, 11), set(), [])

        self.assertCalledOnce(mock_add_location_dependencies, graph, (1, 11),
                              set())
    def test_should_add_dependencies_to_graph(
        self, mock_add_location_dependencies
    ):
        worksheet = Worksheet()
        worksheet[99, 98].formula = '=foobar'
        worksheet[1, 11].formula = '=foo'
        worksheet[1, 11].dependencies = [(99, 98)]
        graph = sentinel.graph

        _generate_cell_subgraph(worksheet, graph, (1, 11), set(), [])

        self.assertEqual(
            mock_add_location_dependencies.call_args,
            ((graph, (1, 11), set([(99, 98)])), {}),
        )
    def test_should_remove_dependencies_with_errors_and_empty_cells(
        self, mock_add_location_dependencies
    ):
        worksheet = Worksheet()
        worksheet[1, 1].formula = '1'
        worksheet[1, 2].error = CycleError([])
        worksheet[1, 3].error = SyntaxError('')
        worksheet[1, 11].formula = '=foo'
        worksheet[1, 11].dependencies = [(1, 1), (1, 2), (1, 3), (1, 4)]
        graph = sentinel.graph

        _generate_cell_subgraph(worksheet, graph, (1, 11), set(), [])

        self.assertCalledOnce(mock_add_location_dependencies,
                              graph, (1, 11), set())
示例#25
0
    def test_should_add_location_to_visited_set_after_recursing_deps(
            self, mock_generate_cell_subgraph):
        visited = set()
        visited_set_at_time_of_recursive_call = []
        # NB: Clone visited or changes will be reflected in the one we store
        mock_generate_cell_subgraph.side_effect = lambda *_: visited_set_at_time_of_recursive_call.append(
            set(visited))

        worksheet = Worksheet()
        worksheet[1, 2].formula = '=23'
        worksheet[1, 2].dependencies = [(3, 4)]

        _generate_cell_subgraph(worksheet, sentinel.graph, (1, 2), visited, [])

        self.assertEquals(visited_set_at_time_of_recursive_call[0], set())
        self.assertEquals(visited, set([(1, 2)]))
        self.assertTrue(mock_generate_cell_subgraph.called)
示例#26
0
    def test_should_not_recurse_into_existing_cycle_errors_or_include_them_in_its_deps(
            self, mock_recursive_call):
        cycle_error = CycleError([(1, 2), (3, 4), (1, 2)])
        worksheet = Worksheet()
        worksheet[1, 2].error = cycle_error
        worksheet[3, 4].error = cycle_error
        worksheet[1, 3].formula = "=foo"
        worksheet[1, 3].dependencies = [(3, 4)]

        visited = set([(1, 2), (3, 4)])
        graph = {}
        _generate_cell_subgraph(worksheet, graph, (1, 3), visited, [])

        dep_cell_calls = [c[0][2] for c in mock_recursive_call.call_args_list]
        self.assertNotIn(dep_cell_calls, (3, 4))
        self.assertEquals(visited, set([(1, 2), (1, 3), (3, 4)]))
        self.assertEquals(graph, {(1, 3): Node((1, 3), set())})
    def test_should_add_location_to_visited_set_after_recursing_deps(
        self, mock_generate_cell_subgraph
    ):
        visited = set()
        visited_set_at_time_of_recursive_call = []
        # NB: Clone visited or changes will be reflected in the one we store
        mock_generate_cell_subgraph.side_effect = lambda *_: visited_set_at_time_of_recursive_call.append(set(visited))

        worksheet = Worksheet()
        worksheet[1, 2].formula = '=23'
        worksheet[1, 2].dependencies = [(3, 4)]

        _generate_cell_subgraph(worksheet, sentinel.graph, (1, 2), visited, [])

        self.assertEquals(visited_set_at_time_of_recursive_call[0], set())
        self.assertEquals(visited, set([(1, 2)]))
        self.assertTrue(mock_generate_cell_subgraph.called)
    def test_should_not_recurse_into_existing_cycle_errors_or_include_them_in_its_deps(
        self, mock_recursive_call
    ):
        cycle_error = CycleError([(1, 2), (3, 4), (1, 2)])
        worksheet = Worksheet()
        worksheet[1, 2].error = cycle_error
        worksheet[3, 4].error = cycle_error
        worksheet[1, 3].formula = "=foo"
        worksheet[1, 3].dependencies = [(3, 4)]

        visited = set([(1, 2), (3, 4)])
        graph = {}
        _generate_cell_subgraph(worksheet, graph, (1, 3), visited, [])

        dep_cell_calls = [c[0][2] for c in mock_recursive_call.call_args_list]
        self.assertNotIn(dep_cell_calls, (3, 4))
        self.assertEquals(visited, set([(1, 2), (1, 3), (3, 4)]))
        self.assertEquals(graph, {(1, 3): Node((1, 3), set())})
示例#29
0
 def test_should_safely_handle_nonexistent_location(self):
     empty_worksheet = {}
     _generate_cell_subgraph(empty_worksheet, sentinel.graph, (1, 2), set(),
                             [])
 def test_should_safely_handle_nonexistent_location(self):
     empty_worksheet = {}
     _generate_cell_subgraph(empty_worksheet, sentinel.graph, (1, 2), set(), [])