Beispiel #1
0
    def test_render_truncate_and_sanitize(self):
        calls = []

        retval = ProcessResult(pd.DataFrame({'A': [1]}))
        retval.truncate_in_place_if_too_big = lambda: calls.append('truncate')
        retval.sanitize_in_place = lambda: calls.append('sanitize')

        lm = LoadedModule('int', '1', False, render_impl=lambda _a, _b: retval)
        with self.assertLogs():
            lm.render(MockParams(), pd.DataFrame(), fetch_result=None)
        self.assertEqual(calls, ['truncate', 'sanitize'])
Beispiel #2
0
    def test_render_truncate(self):
        calls = []

        retval = ProcessResult(pd.DataFrame({"A": [1]}))
        retval.truncate_in_place_if_too_big = lambda: calls.append("truncate")

        lm = LoadedModule(
            "int", "1", ParamDType.Dict({}), render_impl=lambda _a, _b: retval
        )
        with self.assertLogs():
            lm.render(ProcessResult(), {}, tab_name="x", fetch_result=None)
        self.assertEqual(calls, ["truncate"])
Beispiel #3
0
    def test_render_truncate(self):
        calls = []

        retval = ProcessResult(pd.DataFrame({'A': [1]}))
        retval.truncate_in_place_if_too_big = lambda: calls.append('truncate')

        lm = LoadedModule('int',
                          '1',
                          ParamDType.Dict({}),
                          render_impl=lambda _a, _b: retval)
        with self.assertLogs():
            lm.render(ProcessResult(), {}, tab_name='x', fetch_result=None)
        self.assertEqual(calls, ['truncate'])
Beispiel #4
0
    def test_render_with_tab_name(self):
        passed_tab_name = None

        def render(table, params, *, tab_name):
            nonlocal passed_tab_name
            passed_tab_name = tab_name

        in_result = ProcessResult(pd.DataFrame({'A': [0]}))

        lm = LoadedModule('int', '1', ParamDType.Dict({}), render_impl=render)
        with self.assertLogs():
            lm.render(in_result, {}, 'Tab X', None)

        self.assertEqual(passed_tab_name, 'Tab X')
Beispiel #5
0
    def test_render_dynamic_default(self):
        lm = LoadedModule('int', '1', True)
        with self.assertLogs():
            result = lm.render(MockParams(),
                               pd.DataFrame({'A': [1]}),
                               fetch_result=None)

        self.assertEqual(result, ProcessResult(pd.DataFrame({'A': [1]})))
Beispiel #6
0
    def test_render_dynamic_default(self):
        lm = LoadedModule('int', '1', ParamDType.Dict({}))
        with self.assertLogs():
            result = lm.render(ProcessResult(pd.DataFrame({'A': [1]})), {},
                               tab_name='x',
                               fetch_result=None)

        self.assertEqual(result, ProcessResult(pd.DataFrame({'A': [1]})))
Beispiel #7
0
    def test_render_with_input_columns(self):
        passed_columns = []

        def render(table, params, *, input_columns, **kwargs):
            nonlocal passed_columns
            passed_columns = input_columns
            return pd.DataFrame({"A": [2]})

        in_result = ProcessResult(pd.DataFrame({"A": [0]}))
        params = {"foo": "bar"}

        lm = LoadedModule("int", "1", ParamDType.Dict({}), render_impl=render)
        with self.assertLogs():
            lm.render(in_result, params, tab_name="x", fetch_result=None)

        self.assertEqual(len(passed_columns), 1)
        self.assertEqual(passed_columns["A"].name, "A")
        self.assertEqual(passed_columns["A"].type, "number")
Beispiel #8
0
    def test_render_with_input_columns(self):
        passed_columns = []

        def render(table, params, *, input_columns, **kwargs):
            nonlocal passed_columns
            passed_columns = input_columns
            return pd.DataFrame({'A': [2]})

        in_result = ProcessResult(pd.DataFrame({'A': [0]}))
        params = {'foo': 'bar'}

        lm = LoadedModule('int', '1', ParamDType.Dict({}), render_impl=render)
        with self.assertLogs():
            lm.render(in_result, params, tab_name='x', fetch_result=None)

        self.assertEqual(len(passed_columns), 1)
        self.assertEqual(passed_columns['A'].name, 'A')
        self.assertEqual(passed_columns['A'].type, 'number')
Beispiel #9
0
    def test_render_dynamic_default(self):
        lm = LoadedModule("int", "1", ParamDType.Dict({}))
        with self.assertLogs():
            result = lm.render(
                ProcessResult(pd.DataFrame({"A": [1]})),
                {},
                tab_name="x",
                fetch_result=None,
            )

        self.assertEqual(result, ProcessResult(pd.DataFrame({"A": [1]})))
Beispiel #10
0
    def test_render_use_input_columns_as_try_fallback_columns(self):
        def render(table, params):
            return pd.DataFrame({'A': [1]})

        lm = LoadedModule('int', '1', ParamDType.Dict({}), render_impl=render)
        column = Column('A', ColumnType.NUMBER('{:,d}'))
        with self.assertLogs():
            result = lm.render(ProcessResult(pd.DataFrame({'A': [1]}),
                                             columns=[column]), {},
                               tab_name='x',
                               fetch_result=None)

        self.assertEqual(result.columns, [column])
Beispiel #11
0
    def test_render_format_columns(self):
        # More of an integration test....
        def render(table, params):
            return {
                "dataframe": pd.DataFrame({"A": [1]}),
                "column_formats": {"A": "{:,d}"},
            }

        lm = LoadedModule("int", "1", ParamDType.Dict({}), render_impl=render)
        with self.assertLogs():
            result = lm.render(ProcessResult(), {}, tab_name="x", fetch_result=None)

        self.assertEqual(result.columns, [Column("A", ColumnType.NUMBER("{:,d}"))])
    def test_render_cannot_coerce_output(self):
        """Log and display error to user when module output is invalid."""
        def render(table, params, **kwargs):
            return {'foo': 'bar'}  # not a valid retval

        lm = LoadedModule('int', '1', render_impl=render)
        with self.assertLogs(level=logging.ERROR):
            result = lm.render(ProcessResult(), {},
                               tab_name='x',
                               fetch_result=None)

        _, lineno = inspect.getsourcelines(render)
        self.assertRegex(result.error,
                         (r'ValueError: ProcessResult input must only contain '
                          r'\{dataframe, error, json, quick_fixes\} '))
Beispiel #13
0
    def test_render_use_input_columns_as_try_fallback_columns(self):
        def render(table, params):
            return pd.DataFrame({"A": [1]})

        lm = LoadedModule("int", "1", ParamDType.Dict({}), render_impl=render)
        column = Column("A", ColumnType.NUMBER("{:,d}"))
        with self.assertLogs():
            result = lm.render(
                ProcessResult(pd.DataFrame({"A": [1]}), columns=[column]),
                {},
                tab_name="x",
                fetch_result=None,
            )

        self.assertEqual(result.columns, [column])
Beispiel #14
0
    def test_render_invalid_return_dict_is_error(self):
        def render(table, params):
            return {'table': pd.DataFrame({'A': [1]})}  # should be 'dataframe'

        lm = LoadedModule('int', '1', ParamDType.Dict({}), render_impl=render)
        with self.assertLogs():
            result = lm.render(ProcessResult(), {},
                               tab_name='x',
                               fetch_result=None)

        self.assertRegex(
            result.error,
            ('Something unexpected happened. We have been notified and are '
             'working to fix it. If this persists, contact us. Error code: '
             'ProcessResult input must only contain {dataframe, error, json, '
             'quick_fixes, column_formats}'))
Beispiel #15
0
    def test_render_static_exception(self):
        class Ick(Exception):
            pass

        def render(params, table, **kwargs):
            raise Ick('Oops')

        lm = LoadedModule('int', '1', False, render_impl=render)
        with self.assertLogs():
            result = lm.render(MockParams(), pd.DataFrame(), fetch_result=None)

        _, lineno = inspect.getsourcelines(render)

        self.assertEqual(
            result,
            ProcessResult(error=(
                f'Ick: Oops at line {lineno + 1} of test_LoadedModule.py')))
Beispiel #16
0
    def test_render_cannot_coerce_output(self):
        """Log and display error to user when module output is invalid."""
        def render(table, params, **kwargs):
            return {'foo': 'bar'}  # not a valid retval

        lm = LoadedModule('int', '1', ParamDType.Dict({}), render_impl=render)
        with self.assertLogs(level=logging.ERROR):
            result = lm.render(ProcessResult(), {},
                               tab_name='x',
                               fetch_result=None)

        _, lineno = inspect.getsourcelines(render)
        self.assertRegex(
            result.error,
            ('Something unexpected happened. We have been notified and are '
             'working to fix it. If this persists, contact us. Error code: '
             'ProcessResult input must only contain {dataframe, error, json, '
             'quick_fixes, column_formats}'))
Beispiel #17
0
    def test_render_format_columns(self):
        # More of an integration test....
        def render(table, params):
            return {
                'dataframe': pd.DataFrame({'A': [1]}),
                'column_formats': {
                    'A': '{:,d}'
                },
            }

        lm = LoadedModule('int', '1', ParamDType.Dict({}), render_impl=render)
        with self.assertLogs():
            result = lm.render(ProcessResult(), {},
                               tab_name='x',
                               fetch_result=None)

        self.assertEqual(result.columns, [
            Column('A', ColumnType.NUMBER('{:,d}')),
        ])
Beispiel #18
0
    def test_render_exception(self):
        class Ick(Exception):
            pass

        def render(table, params, **kwargs):
            raise Ick('Oops')

        lm = LoadedModule('int', '1', ParamDType.Dict({}), render_impl=render)
        with self.assertLogs(level=logging.ERROR):
            result = lm.render(ProcessResult(), {},
                               tab_name='x',
                               fetch_result=None)

        _, lineno = inspect.getsourcelines(render)

        self.assertEqual(
            result,
            ProcessResult(error=(
                f'Ick: Oops at line {lineno + 1} of test_LoadedModule.py')))
Beispiel #19
0
    def test_render_dynamic_with_no_kwargs(self):
        args = None

        def render(table, params):
            nonlocal args
            args = (table, params)
            return ProcessResult(pd.DataFrame({'A': [1]}))

        in_table = pd.DataFrame({'A': [0]})
        params = MockParams(foo='bar')
        expected = ProcessResult(pd.DataFrame({'A': [1]}))

        lm = LoadedModule('int', '1', True, render_impl=render)
        with self.assertLogs():
            result = lm.render(params, in_table, fetch_result=None)
        self.assertIs(args[0], in_table)
        self.assertEqual(args[1], {'foo': 'bar'})
        self.assertEqual(len(args), 2)
        self.assertEqual(result, expected)
Beispiel #20
0
    def test_render_invalid_retval(self):
        def render(table, params):
            return pd.DataFrame({'A': [True, False]})  # we don't support bool

        lm = LoadedModule('int', '1', ParamDType.Dict({}), render_impl=render)
        with self.assertLogs(level=logging.ERROR) as cm:
            result = lm.render(ProcessResult(), {},
                               tab_name='x',
                               fetch_result=None)
            # Should log an exception, which will email us
            self.assertRegex(cm.output[0],
                             r'Exception coercing int\.render output')
            self.assertRegex(cm.output[0],
                             r"unsupported dtype dtype\('bool'\)")
        # Should inform the user, who can follow up with the dev
        self.assertEqual(
            result,
            ProcessResult(error=(
                'Something unexpected happened. We have been notified and are '
                'working to fix it. If this persists, contact us. Error code: '
                "unsupported dtype dtype('bool') in column 'A'")))
Beispiel #21
0
    def test_render_static_with_fetch_result(self):
        args = None

        def render(params, table, *, fetch_result, **kwargs):
            nonlocal args
            args = (params, table, fetch_result, kwargs)
            return ProcessResult(pd.DataFrame({'A': [2]}))

        in_table = pd.DataFrame({'A': [0]})
        params = MockParams(foo='bar')
        fetch_result = ProcessResult(pd.DataFrame({'A': [1]}))
        expected = ProcessResult(pd.DataFrame({'A': [2]}))

        lm = LoadedModule('int', '1', False, render_impl=render)
        with self.assertLogs():
            result = lm.render(params, in_table, fetch_result=fetch_result)
        self.assertIs(args[0], params)
        self.assertIs(args[1], in_table)
        self.assertIs(args[2], fetch_result)
        self.assertEqual(args[3], {})
        self.assertEqual(result, expected)
Beispiel #22
0
    def test_render_with_no_kwargs(self):
        args = None

        def render(table, params):
            nonlocal args
            args = (table, params)
            return pd.DataFrame({"A": [1]})

        in_table = pd.DataFrame({"A": [0]})
        params = {"foo": "bar"}
        expected = ProcessResult(pd.DataFrame({"A": [1]}))

        lm = LoadedModule("int", "1", ParamDType.Dict({}), render_impl=render)
        with self.assertLogs():
            result = lm.render(
                ProcessResult(in_table), params, tab_name="x", fetch_result=None
            )
        self.assertIs(args[0], in_table)
        self.assertIs(args[1], params)
        self.assertEqual(len(args), 2)
        self.assertEqual(result, expected)
Beispiel #23
0
    def test_render_dynamic_exception(self):
        class Ick(Exception):
            pass

        def render(table, params, **kwargs):
            # Pre
            # am
            # bl
            # e
            #
            # The user never wrote the top 6 lines of code
            raise Ick('Oops')

        lm = LoadedModule('int', '1', True, render_impl=render)
        with self.assertLogs():
            result = lm.render(MockParams(), pd.DataFrame(), fetch_result=None)

        _, lineno = inspect.getsourcelines(render)
        self.assertEqual(
            result,
            ProcessResult(error=(
                f'Ick: Oops at line {lineno + 1} of test_LoadedModule.py')))
Beispiel #24
0
    def test_render_with_fetch_result(self):
        args = None

        def render(table, params, *, fetch_result):
            nonlocal args
            args = (table, params, fetch_result)
            return pd.DataFrame({'A': [2]})

        in_table = pd.DataFrame({'A': [0]})
        params = {'foo': 'bar'}
        fetch_result = ProcessResult(pd.DataFrame({'A': [1]}))
        expected = ProcessResult(pd.DataFrame({'A': [2]}))

        lm = LoadedModule('int', '1', ParamDType.Dict({}), render_impl=render)
        with self.assertLogs():
            result = lm.render(ProcessResult(in_table),
                               params,
                               tab_name='x',
                               fetch_result=fetch_result)
        self.assertIs(args[0], in_table)
        self.assertIs(args[1], params)
        self.assertIs(args[2], fetch_result)
        self.assertEqual(result, expected)