def test_evaluate_expression_syntax_error(self):
     df = pd.DataFrame(data=[[nan, 'gnu', 3], [4, 'gnat', '{{((((*+-/ x y heres_a_syntax_error!!!!!!!!!!!!!!!!}}']],
                       columns=['a', 'b', 'c'])
     col_specs = {n: ColumnMetadata(Unit(u)) for n, u in zip(['a', 'b', 'c'], ['-', 'text', 'm'])}
     t = Table(df=df, name='some_table', col_specs=col_specs, destinations=['success', 'glory'])
     with raises(SyntaxError, match=r"Syntax error in expression in table 'some_table', column 2, row 1"):
         t.evaluate_expressions({'x': 7, 'y': 9}, inplace=False)
    def test_evaluate_expressions(self, some_table: Table):
        env: Environment = make_root_environment().define('x', 42).define('y', 7)
        assert some_table.evaluate_expressions(env, inplace=False).df.iloc[1, 2] == 49

        context_dict = {'x': 7, 'y': 9}
        assert some_table.evaluate_expressions(context_dict, inplace=False).df.iloc[1, 2] == 16

        env.update([('y', 10)])
        some_table.evaluate_expressions(env, inplace=True)
        assert some_table.df.iloc[1, 2] == 52
 def test_init_errors(self, some_df, col_specs):
     with pytest.raises(ValueError):
         too_short_col_specs = {n: col_specs[n] for n in col_specs if n != 'b'}
         Table(df=some_df, name='adequate_table', col_specs=too_short_col_specs)
     with pytest.raises(ValueError):
         destination_with_illegal_space = ['ok', 'definitely not ok!', 'ok_again']
         Table(df=some_df, name='adequate_table', destinations=destination_with_illegal_space)
     with raises(ValueError):
         destinations_with_illegal_duplicates = ['ok', 'you_again', 'you_again']
         Table(df=some_df, name='adequate_table', destinations=destinations_with_illegal_duplicates)
 def test_to_excel(self, some_table: Table):
     wb = openpyxl.Workbook()
     ws: Worksheet = wb.active
     some_table.to_excel(ws)
     assert ws.cell(row=1, column=1).value == f'**{some_table.name}'
     assert ws.cell(2, 1).value == f'{" ".join(some_table.destinations)}'
     assert ws.cell(3, 2).value == 'b'
     assert ws.cell(4, 3).value == 'm'
     assert ws.cell(5, 1).value == '-'
     assert ws.cell(6, 3).value == '{{(+ x y)}}'
    def test_df_setter(self, some_table: Table):
        df_with_subset_of_columns = pd.DataFrame(data=[[nan, 3], [4, 666]], columns=['a', 'c'])
        some_table.df = df_with_subset_of_columns
        assert some_table.col_names == ['a', 'c']
        assert some_table.col_units == ['-', 'm']

        df_with_new_unknown_column = pd.DataFrame(data=[[nan, 'gnu', 3], [4, 'gnat', '{{(+ x y)}}']],
                                                  columns=['some_unknown_column', 'b', 'c'])
        with pytest.raises(ValueError):
            some_table.df = df_with_new_unknown_column
 def test_to_csv(self, some_table: Table):
     out = io.StringIO()
     some_table.to_csv(out)
     assert out.getvalue() == dedent("""\
         **some_table;;
         success glory
         a;b;c
         -;text;m
         -;gnu;3
         4.0;gnat;{{(+ x y)}}
         
         """)
 def test_convert_to_ref_units(self):
     df = pd.DataFrame([
         [11, 12, 13],
         [21, 22, 23]], columns=['a', 'b', 'c'])
     cs = {n: ColumnMetadata(Unit(u)) for n, u in zip(['a', 'b', 'c'], ['m', 'mm', 'km'])}
     t = Table(df, name='Fool', col_specs=cs)
     cup = CustomUnitPolicy([
         ScaleUnitConversion(Unit('mm'), Unit('m'), 0.001),
         ScaleUnitConversion(Unit('km'), Unit('m'), 1000)])
     t_ref = t.convert_to_ref_units(cup, inplace=False)
     assert t_ref.col_units == [Unit('m')] * 3
     assert (np.array(t_ref.df) == np.array([[11, 0.012, 13000],
                                             [21, 0.022, 23000]])).all()
    def test_convert_to_ref_units_unknown_unit(self):
        df = pd.DataFrame([
            [11, 12, 13],
            [21, 22, 23]], columns=['a', 'b', 'c'])
        cs = {n: ColumnMetadata(Unit(u)) for n, u in zip(['a', 'b', 'c'], ['m', 'mm', 'km'])}
        t = Table(df, name='Fool', col_specs=cs)
        cup_no_km = CustomUnitPolicy([ScaleUnitConversion(Unit('mm'), Unit('m'), 0.001)])
        t_ref_no_km = t.convert_to_ref_units(cup_no_km, inplace=False, units_not_in_policy='ignore')
        assert t_ref_no_km.col_units == [Unit('m'), Unit('m'), Unit('km')]
        assert (np.array(t_ref_no_km.df) == np.array([[11, 0.012, 13],
                                                      [21, 0.022, 23]])).all()

        with raises(ValueError):
            t.convert_to_ref_units(cup_no_km, inplace=False, units_not_in_policy='raise')
 def test_convert_to_home_units(self):
     df = pd.DataFrame([
         [11, 12, 13],
         [21, 22, 23]], columns=['a', 'b', 'c'])
     cs = {n: ColumnMetadata(Unit(u), Unit(hu)) for n, u, hu in zip(
         ['a', 'b', 'c'], ['m', 'm', 'm'], ['m', 'mm', 'km'])}
     t = Table(df, name='Fool', col_specs=cs)
     cup = CustomUnitPolicy([
         ScaleUnitConversion(Unit('mm'), Unit('m'), 0.001),
         ScaleUnitConversion(Unit('km'), Unit('m'), 1000)])
     t_home = t.convert_to_home_units(cup)
     assert t_home.col_units == [Unit('m'), Unit('mm'), Unit('km')]
     assert (np.array(t_home.df) == np.array([[11, 12000, 0.013],
                                              [21, 22000, 0.023]])).all()
 def test_to_csv_with_format(self, some_table_with_digits: Table):
     out = io.StringIO()
     some_table_with_digits.to_csv(out)
     print(out.getvalue())
     assert out.getvalue() == dedent("""\
         **some_table_with_digits;;
         success glory
         a;b;c
         -;text;m
         -;gnu;3.2341e+00
         $4.12;gnat;2.3000e-02
         $0.40;galah;4.2010e+01
         $0.04;gentoo;4.3232e+04
         $4,000.04;gerbil;4.3232e+04
         
         """)
 def test_copy(self, some_table: Table):
     t1 = some_table
     t2 = some_table.copy()
     assert t1.df is not t2.df  # checking it's actually a new copy
     assert t2.name == t1.name
     assert t2.destinations == t1.destinations
     assert t2.col_names == t1.col_names
     assert t2.col_units == t1.col_units
     pd.testing.assert_frame_equal(t1.df, t2.df)
 def test_to_excel_with_digits(self, some_table_with_digits: Table):
     wb = openpyxl.Workbook()
     ws: Worksheet = wb.active
     some_table_with_digits.to_excel(ws)
     assert ws.cell(row=1, column=1).value == f'**{some_table_with_digits.name}'
     assert ws.cell(2, 1).value == f'{" ".join(some_table_with_digits.destinations)}'
     assert ws.cell(3, 2).value == 'b'
     assert ws.cell(4, 3).value == 'm'
     assert ws.cell(5, 1).value == '-'
     assert ws.cell(5, 3).value == '3.2341e+00'
     assert ws.cell(6, 1).value == '$4.12'
     assert ws.cell(6, 3).value == '2.3000e-02'
     assert ws.cell(7, 1).value == '$0.40'
     assert ws.cell(7, 3).value == '4.2010e+01'
     assert ws.cell(8, 1).value == '$0.04'
     assert ws.cell(8, 3).value == '4.3232e+04'
     assert ws.cell(9, 1).value == '$4,000.04'
     assert ws.cell(9, 3).value == '4.3232e+04'
 def test_init_with_col_specs(self, some_df, col_specs):
     t = Table(df=some_df, name='adequate_table', col_specs=col_specs)
     assert t.name == 'adequate_table'
     assert t.destinations == ['all']
     assert t.df.iloc[1, 0] == 4
     assert t.col_names == ['a', 'b', 'c']
     assert t.col_units == ['-', 'text', 'm']
     assert t.col_specs == col_specs
     assert len(t) == 2
 def test_to_csv_nonstring_colnames_and_destinations(self):
     # PS-53 Bundle.to_csv() fails when column names are not strings
     nonstring_colnames = [1.234, 666.0, 42.0]
     nonstring_destinations = [1984, 2001.2001]
     df = pd.DataFrame(data=[[nan, 'gnu', 3], [4, 'gnat', '{{(+ x y)}}']], columns=nonstring_colnames)
     col_specs = {n: ColumnMetadata(Unit(u)) for n, u in zip(nonstring_colnames, ['-', 'text', 'm'])}
     t = Table(df=df, name='some_table', col_specs=col_specs,
               destinations=nonstring_destinations)
     out = io.StringIO()
     t.to_csv(out)
     assert out.getvalue() == dedent("""\
         **some_table;;
         1984 2001.2001
         1.234;666.0;42.0
         -;text;m
         -;gnu;3
         4.0;gnat;{{(+ x y)}}
         
         """)
 def test_init_with_no_col_specs_at_all(self, some_df):
     t = Table(df=some_df, name='adequate_table')
     cs = t.col_specs
     assert list(cs.keys()) == ['a', 'b', 'c']
     assert [cs[col_name].unit for col_name in cs] == ['text', 'text', 'text']
 def some_table_with_digits(self, some_df_with_digits, col_specs_with_format):
     return Table(df=some_df_with_digits, name='some_table_with_digits', col_specs=col_specs_with_format,
                  destinations=['success', 'glory'])
 def some_table(self, some_df, col_specs):
     return Table(df=some_df, name='some_table', col_specs=col_specs, destinations=['success', 'glory'])