Exemplo n.º 1
0
class TestTableCompute(unittest.TestCase):
    def setUp(self):
        self.rows = (
            ('a', 2, 3, 4),
            (None, 3, 5, None),
            ('a', 2, 4, None),
            ('b', 3, 6, None)
        )

        self.number_type = Number()
        self.text_type = Text()

        self.columns = (
            ('one', self.text_type),
            ('two', self.number_type),
            ('three', self.number_type),
            ('four', self.number_type)
        )

        self.table = Table(self.rows, self.columns)

    def test_compute(self):
        new_table = self.table.compute([
            (Formula(self.number_type, lambda r: r['two'] + r['three']), 'number'),
            (Formula(self.text_type, lambda r: (r['one'] or '-') + six.text_type(r['three'])), 'text')
        ])

        self.assertIsNot(new_table, self.table)
        self.assertEqual(len(new_table.rows), 4)
        self.assertEqual(len(new_table.columns), 6)

        self.assertSequenceEqual(new_table.rows[0], ('a', 2, 3, 4, 5, 'a3'))
        self.assertSequenceEqual(new_table.columns['number'], (5, 8, 6, 9))
        self.assertSequenceEqual(new_table.columns['text'], ('a3', '-5', 'a4', 'b6'))

    def test_compute_multiple(self):
        new_table = self.table.compute([
            (Formula(self.number_type, lambda r: r['two'] + r['three']), 'test')
        ])

        self.assertIsNot(new_table, self.table)
        self.assertEqual(len(new_table.rows), 4)
        self.assertEqual(len(new_table.columns), 5)

        self.assertSequenceEqual(new_table.rows[0], ('a', 2, 3, 4, 5))
        self.assertSequenceEqual(new_table.columns['test'], (5, 8, 6, 9))

    def test_compute_with_row_names(self):
        table = Table(self.rows, self.columns, row_names='three')

        new_table = table.compute([
            (Formula(self.number_type, lambda r: r['two'] + r['three']), 'number'),
            (Formula(self.text_type, lambda r: (r['one'] or '-') + six.text_type(r['three'])), 'text')
        ])

        self.assertSequenceEqual(new_table.rows[0], ('a', 2, 3, 4, 5, 'a3'))
        self.assertSequenceEqual(new_table.row_names, (3, 5, 4, 6))
Exemplo n.º 2
0
class TestTableCompute(unittest.TestCase):
    def setUp(self):
        self.rows = (
            ('a', 2, 3, 4),
            (None, 3, 5, None),
            ('a', 2, 4, None),
            ('b', 3, 6, None)
        )

        self.number_type = Number()
        self.text_type = Text()

        self.column_names = [
            'one', 'two', 'three', 'four'
        ]
        self.column_types = [
            self.text_type, self.number_type, self.number_type, self.number_type
        ]

        self.table = Table(self.rows, self.column_names, self.column_types)

    def test_compute(self):
        new_table = self.table.compute([
            (Formula(self.number_type, lambda r: r['two'] + r['three']), 'number'),
            (Formula(self.text_type, lambda r: (r['one'] or '-') + six.text_type(r['three'])), 'text')
        ])

        self.assertIsNot(new_table, self.table)
        self.assertEqual(len(new_table.rows), 4)
        self.assertEqual(len(new_table.columns), 6)

        self.assertSequenceEqual(new_table.rows[0], ('a', 2, 3, 4, 5, 'a3'))
        self.assertSequenceEqual(new_table.columns['number'], (5, 8, 6, 9))
        self.assertSequenceEqual(new_table.columns['text'], ('a3', '-5', 'a4', 'b6'))

    def test_compute_multiple(self):
        new_table = self.table.compute([
            (Formula(self.number_type, lambda r: r['two'] + r['three']), 'test')
        ])

        self.assertIsNot(new_table, self.table)
        self.assertEqual(len(new_table.rows), 4)
        self.assertEqual(len(new_table.columns), 5)

        self.assertSequenceEqual(new_table.rows[0], ('a', 2, 3, 4, 5))
        self.assertSequenceEqual(new_table.columns['test'], (5, 8, 6, 9))

    def test_compute_with_row_names(self):
        table = Table(self.rows, self.column_names, self.column_types, row_names='three')

        new_table = table.compute([
            (Formula(self.number_type, lambda r: r['two'] + r['three']), 'number'),
            (Formula(self.text_type, lambda r: (r['one'] or '-') + six.text_type(r['three'])), 'text')
        ])

        self.assertSequenceEqual(new_table.rows[0], ('a', 2, 3, 4, 5, 'a3'))
        self.assertSequenceEqual(new_table.row_names, (3, 5, 4, 6))
Exemplo n.º 3
0
class TestCompute(AgateTestCase):
    def setUp(self):
        self.rows = (
            ('a', 2, 3, 4),
            (None, 3, 5, None),
            ('a', 2, 4, None),
            ('b', 3, 6, None)
        )

        self.number_type = Number()
        self.text_type = Text()

        self.column_names = [
            'one', 'two', 'three', 'four'
        ]
        self.column_types = [
            self.text_type, self.number_type, self.number_type, self.number_type
        ]

        self.table = Table(self.rows, self.column_names, self.column_types)

    def test_compute(self):
        new_table = self.table.compute([
            ('test', Formula(self.number_type, lambda r: r['two'] + r['three']))
        ])

        self.assertIsNot(new_table, self.table)
        self.assertColumnNames(new_table, ['one', 'two', 'three', 'four', 'test'])
        self.assertColumnTypes(new_table, [Text, Number, Number, Number, Number])

        self.assertSequenceEqual(new_table.rows[0], ('a', 2, 3, 4, 5))
        self.assertSequenceEqual(new_table.columns['test'], (5, 8, 6, 9))

    def test_compute_multiple(self):
        new_table = self.table.compute([
            ('number', Formula(self.number_type, lambda r: r['two'] + r['three'])),
            ('text', Formula(self.text_type, lambda r: (r['one'] or '-') + six.text_type(r['three'])))
        ])

        self.assertIsNot(new_table, self.table)
        self.assertColumnNames(new_table, ['one', 'two', 'three', 'four', 'number', 'text'])
        self.assertColumnTypes(new_table, [Text, Number, Number, Number, Number, Text])

        self.assertSequenceEqual(new_table.rows[0], ('a', 2, 3, 4, 5, 'a3'))
        self.assertSequenceEqual(new_table.columns['number'], (5, 8, 6, 9))
        self.assertSequenceEqual(new_table.columns['text'], ('a3', '-5', 'a4', 'b6'))

    def test_compute_with_row_names(self):
        table = Table(self.rows, self.column_names, self.column_types, row_names='three')

        new_table = table.compute([
            ('number', Formula(self.number_type, lambda r: r['two'] + r['three'])),
            ('text', Formula(self.text_type, lambda r: (r['one'] or '-') + six.text_type(r['three'])))
        ])

        self.assertRowNames(new_table, [3, 5, 4, 6])
Exemplo n.º 4
0
    def test_change_mixed_types(self):
        rows = (("1", "10/24/1978"), ("2", "11/13/1974"))

        column_names = ["number", "date"]
        column_types = [Number(), Date()]

        table = Table(rows, column_names, column_types)

        with self.assertRaises(ValueError):
            table.compute([("test", Change("number", "date"))])
Exemplo n.º 5
0
    def test_change_mixed_types(self):
        rows = (('1', '10/24/1978'), ('2', '11/13/1974'))

        column_names = ['number', 'date']
        column_types = [Number(), Date()]

        table = Table(rows, column_names, column_types)

        with self.assertRaises(ValueError):
            table.compute([('test', Change('number', 'date'))])
Exemplo n.º 6
0
    def test_changed_invalid_types(self):
        rows = ((False, True), (True, False))

        column_names = ['before', 'after']
        column_types = [Boolean(), Boolean()]

        table = Table(rows, column_names, column_types)

        with self.assertRaises(DataTypeError):
            table.compute([('test', Change('before', 'after'))])
Exemplo n.º 7
0
    def test_changed_invalid_types(self):
        rows = ((False, True), (True, False))

        column_names = ["before", "after"]
        column_types = [Boolean(), Boolean()]

        table = Table(rows, column_names, column_types)

        with self.assertRaises(DataTypeError):
            table.compute([("test", Change("before", "after"))])
Exemplo n.º 8
0
    def prepare(self, table):
        """ Prepare a table with comparison items for each row in table
        """
        super(GroupComparison, self).prepare(table)
        self.comparison_tables = {}

        if self.group_by:
            """ Case: Group by category column
            """
            self.groups = {}
            for group_table in table.group_by(self.group_by):
                # Add row name to the grouped tables
                group_table = Table(group_table.rows,
                    column_types=group_table.column_types,
                    column_names=group_table.column_names,
                    row_names=self.key)
                group_name = group_table.rows[0][self.group_by]

                # Apply computation
                group_table = group_table.compute([self._get_computation()])

                self.groups[group_name] = group_table

            for row in table.rows:
                row_key = row[self.key]
                group_name = row[self.group_by]
                self.comparison_tables[row_key] = self.groups[group_name]


        elif self.comparison_column:
            """ Case: Get comparison items from column
            """
            for row in table.rows:
                try:
                    comparison_keys = row[self.comparison_column].split(",")
                except AttributeError:
                    comparison_keys = []

                # Add self to comparison table. Needed to be able to rank
                comparison_keys += [row[self.key]]
                comparison_table = Table(
                    [table.rows[x] for x in comparison_keys],
                    column_types=table.column_types,
                    column_names=table.column_names,
                    row_names=self.key
                )
                # Apply computation
                comparison_table = comparison_table.compute([self._get_computation()])
                self.comparison_tables[row[self.key]] = comparison_table
Exemplo n.º 9
0
    def test_changed_invalid_types(self):
        rows = (
            (False, True),
            (True, False)
        )

        column_names = ['before', 'after']
        column_types = [Boolean(), Boolean()]

        table = Table(rows, column_names, column_types)

        with self.assertRaises(DataTypeError):
            table.compute([
                ('test', Change('before', 'after'))
            ])
Exemplo n.º 10
0
    def test_change_mixed_types(self):
        rows = (
            ('1', '10/24/1978'),
            ('2', '11/13/1974')
        )

        column_names = ['number', 'date']
        column_types = [Number(), Date()]

        table = Table(rows, column_names, column_types)

        with self.assertRaises(DataTypeError):
            table.compute([
                ('test', Change('number', 'date'))
            ])
Exemplo n.º 11
0
    def prepare(self, table):
        """ Prepare a table with comparison items for each row in table
        """
        super(GroupComparison, self).prepare(table)
        self.comparison_tables = {}

        if self.group_by:
            """ Case: Group by category column
            """
            self.groups = {}
            for group_table in table.group_by(self.group_by):
                # Add row name to the grouped tables
                group_table = Table(group_table.rows,
                                    column_types=group_table.column_types,
                                    column_names=group_table.column_names,
                                    row_names=self.key)
                group_name = group_table.rows[0][self.group_by]

                # Apply computation
                group_table = group_table.compute([self._get_computation()])

                self.groups[group_name] = group_table

            for row in table.rows:
                row_key = row[self.key]
                group_name = row[self.group_by]
                self.comparison_tables[row_key] = self.groups[group_name]

        elif self.comparison_column:
            """ Case: Get comparison items from column
            """
            for row in table.rows:
                try:
                    comparison_keys = row[self.comparison_column].split(",")
                except AttributeError:
                    comparison_keys = []

                # Add self to comparison table. Needed to be able to rank
                comparison_keys += [row[self.key]]
                comparison_table = Table(
                    [table.rows[x] for x in comparison_keys],
                    column_types=table.column_types,
                    column_names=table.column_names,
                    row_names=self.key)
                # Apply computation
                comparison_table = comparison_table.compute(
                    [self._get_computation()])
                self.comparison_tables[row[self.key]] = comparison_table
Exemplo n.º 12
0
    def test_change_datetimes(self):
        rows = (
            ('10/4/2015 4:43', '10/7/2015 4:50'),
            ('10/2/2015 12 PM', '9/28/2015 12 PM'),
            ('9/28/2015 12:00:00', '9/1/2015 6 PM')
        )

        datetime_type = DateTime()

        column_names = ['one', 'two']
        column_types = [datetime_type, datetime_type]

        table = Table(rows, column_names, column_types)

        new_table = table.compute([
            ('test', Change('one', 'two'))
        ])

        self.assertIsNot(new_table, table)
        self.assertEqual(len(new_table.rows), 3)
        self.assertEqual(len(new_table.columns), 3)

        self.assertSequenceEqual(new_table.rows[0], (
            datetime.datetime(2015, 10, 4, 4, 43),
            datetime.datetime(2015, 10, 7, 4, 50),
            datetime.timedelta(days=3, minutes=7)
        ))

        self.assertEqual(new_table.columns['test'][0], datetime.timedelta(days=3, minutes=7))
        self.assertEqual(new_table.columns['test'][1], datetime.timedelta(days=-4))
        self.assertEqual(new_table.columns['test'][2], datetime.timedelta(days=-26, hours=-18))
Exemplo n.º 13
0
    def test_change_timedeltas(self):
        rows = (
            ('4:15', '8:18'),
            ('4h 2m', '2h'),
            ('4 weeks', '27 days')
        )

        timedelta_type = TimeDelta()

        column_names = ['one', 'two']
        column_types = [timedelta_type, timedelta_type]

        table = Table(rows, column_names, column_types)

        new_table = table.compute([
            ('test', Change('one', 'two'))
        ])

        self.assertIsNot(new_table, table)
        self.assertEqual(len(new_table.rows), 3)
        self.assertEqual(len(new_table.columns), 3)

        self.assertSequenceEqual(new_table.rows[0], (
            datetime.timedelta(minutes=4, seconds=15),
            datetime.timedelta(minutes=8, seconds=18),
            datetime.timedelta(minutes=4, seconds=3)
        ))
        self.assertEqual(new_table.columns['test'][0], datetime.timedelta(minutes=4, seconds=3))
        self.assertEqual(new_table.columns['test'][1], datetime.timedelta(hours=-2, minutes=-2))
        self.assertEqual(new_table.columns['test'][2], datetime.timedelta(days=-1))
Exemplo n.º 14
0
    def test_change_datetimes(self):
        rows = (
            ("10/4/2015 4:43", "10/7/2015 4:50"),
            ("10/2/2015 12 PM", "9/28/2015 12 PM"),
            ("9/28/2015 12:00:00", "9/1/2015 6 PM"),
        )

        datetime_type = DateTime()

        column_names = ["one", "two"]
        column_types = [datetime_type, datetime_type]

        table = Table(rows, column_names, column_types)

        new_table = table.compute([("test", Change("one", "two"))])

        self.assertIsNot(new_table, table)
        self.assertEqual(len(new_table.rows), 3)
        self.assertEqual(len(new_table.columns), 3)

        self.assertSequenceEqual(
            new_table.rows[0],
            (
                datetime.datetime(2015, 10, 4, 4, 43),
                datetime.datetime(2015, 10, 7, 4, 50),
                datetime.timedelta(days=3, minutes=7),
            ),
        )

        self.assertEqual(new_table.columns["test"][0], datetime.timedelta(days=3, minutes=7))
        self.assertEqual(new_table.columns["test"][1], datetime.timedelta(days=-4))
        self.assertEqual(new_table.columns["test"][2], datetime.timedelta(days=-26, hours=-18))
Exemplo n.º 15
0
    def test_change_timedeltas(self):
        rows = (("4:15", "8:18"), ("4h 2m", "2h"), ("4 weeks", "27 days"))

        timedelta_type = TimeDelta()

        column_names = ["one", "two"]
        column_types = [timedelta_type, timedelta_type]

        table = Table(rows, column_names, column_types)

        new_table = table.compute([("test", Change("one", "two"))])

        self.assertIsNot(new_table, table)
        self.assertEqual(len(new_table.rows), 3)
        self.assertEqual(len(new_table.columns), 3)

        self.assertSequenceEqual(
            new_table.rows[0],
            (
                datetime.timedelta(minutes=4, seconds=15),
                datetime.timedelta(minutes=8, seconds=18),
                datetime.timedelta(minutes=4, seconds=3),
            ),
        )
        self.assertEqual(new_table.columns["test"][0], datetime.timedelta(minutes=4, seconds=3))
        self.assertEqual(new_table.columns["test"][1], datetime.timedelta(hours=-2, minutes=-2))
        self.assertEqual(new_table.columns["test"][2], datetime.timedelta(days=-1))
Exemplo n.º 16
0
    def test_change_dates(self):
        rows = (('October 4th', 'October 7th'),
                ('October 2nd', 'September 28'), ('September 28th', '9/1/15'))

        date_type = DateType()

        columns = (('one', date_type), ('two', date_type))

        table = Table(rows, columns)

        new_table = table.compute([('test', Change('one', 'two'))])

        self.assertIsNot(new_table, table)
        self.assertEqual(len(new_table.rows), 3)
        self.assertEqual(len(new_table.columns), 3)

        self.assertSequenceEqual(
            new_table.rows[0],
            (datetime.date(2015, 10, 4), datetime.date(
                2015, 10, 7), datetime.timedelta(days=3)))
        self.assertEqual(new_table.columns['test'][0],
                         datetime.timedelta(days=3))
        self.assertEqual(new_table.columns['test'][1],
                         datetime.timedelta(days=-4))
        self.assertEqual(new_table.columns['test'][2],
                         datetime.timedelta(days=-27))
Exemplo n.º 17
0
    def test_change_datetimes(self):
        rows = (('October 4th 4:43', 'October 7th, 4:50'),
                ('October 2nd, 12 PM', 'September 28, 12 PM'),
                ('September 28th, 12:00:00', '9/1/15, 6 PM'))

        datetime_type = DateTimeType()

        columns = (('one', datetime_type), ('two', datetime_type))

        table = Table(rows, columns)

        new_table = table.compute([('test', Change('one', 'two'))])

        self.assertIsNot(new_table, table)
        self.assertEqual(len(new_table.rows), 3)
        self.assertEqual(len(new_table.columns), 3)

        self.assertSequenceEqual(new_table.rows[0], (datetime.datetime(
            2015, 10, 4, 4, 43), datetime.datetime(
                2015, 10, 7, 4, 50), datetime.timedelta(days=3, minutes=7)))
        self.assertEqual(new_table.columns['test'][0],
                         datetime.timedelta(days=3, minutes=7))
        self.assertEqual(new_table.columns['test'][1],
                         datetime.timedelta(days=-4))
        self.assertEqual(new_table.columns['test'][2],
                         datetime.timedelta(days=-26, hours=-18))
Exemplo n.º 18
0
    def test_change_dates(self):
        rows = (
            ('October 4th', 'October 7th'),
            ('October 2nd', 'September 28'),
            ('September 28th', '9/1/15')
        )

        date_type = DateType()

        columns = (
            ('one', date_type),
            ('two', date_type)
        )

        table = Table(rows, columns)

        new_table = table.compute([
            ('test', Change('one', 'two'))
        ])

        self.assertIsNot(new_table, table)
        self.assertEqual(len(new_table.rows), 3)
        self.assertEqual(len(new_table.columns), 3)

        self.assertSequenceEqual(new_table.rows[0], (
            datetime.date(2015, 10, 4),
            datetime.date(2015, 10, 7),
            datetime.timedelta(days=3)
        ))
        self.assertEqual(new_table.columns['test'][0], datetime.timedelta(days=3))
        self.assertEqual(new_table.columns['test'][1], datetime.timedelta(days=-4))
        self.assertEqual(new_table.columns['test'][2], datetime.timedelta(days=-27))
Exemplo n.º 19
0
    def test_change_datetimes(self):
        rows = (
            ('October 4th 4:43', 'October 7th, 4:50'),
            ('October 2nd, 12 PM', 'September 28, 12 PM'),
            ('September 28th, 12:00:00', '9/1/15, 6 PM')
        )

        datetime_type = DateTimeType()

        columns = (
            ('one', datetime_type),
            ('two', datetime_type)
        )

        table = Table(rows, columns)

        new_table = table.compute([
            ('test', Change('one', 'two'))
        ])

        self.assertIsNot(new_table, table)
        self.assertEqual(len(new_table.rows), 3)
        self.assertEqual(len(new_table.columns), 3)

        self.assertSequenceEqual(new_table.rows[0], (
            datetime.datetime(2015, 10, 4, 4, 43),
            datetime.datetime(2015, 10, 7, 4, 50),
            datetime.timedelta(days=3, minutes=7)
        ))
        self.assertEqual(new_table.columns['test'][0], datetime.timedelta(days=3, minutes=7))
        self.assertEqual(new_table.columns['test'][1], datetime.timedelta(days=-4))
        self.assertEqual(new_table.columns['test'][2], datetime.timedelta(days=-26, hours=-18))
Exemplo n.º 20
0
    def test_change_dates(self):
        rows = (
            ('10/4/2015', '10/7/2015'),
            ('10/2/2015', '9/28/2015'),
            ('9/28/2015', '9/1/2015')
        )

        date_type = Date()

        column_names = ['one', 'two']
        column_types = [date_type, date_type]

        table = Table(rows, column_names, column_types)

        new_table = table.compute([
            ('test', Change('one', 'two'))
        ])

        self.assertIsNot(new_table, table)
        self.assertEqual(len(new_table.rows), 3)
        self.assertEqual(len(new_table.columns), 3)

        self.assertSequenceEqual(new_table.rows[0], (
            datetime.date(2015, 10, 4),
            datetime.date(2015, 10, 7),
            datetime.timedelta(days=3)
        ))

        self.assertEqual(new_table.columns['test'][0], datetime.timedelta(days=3))
        self.assertEqual(new_table.columns['test'][1], datetime.timedelta(days=-4))
        self.assertEqual(new_table.columns['test'][2], datetime.timedelta(days=-27))
Exemplo n.º 21
0
class TestTableCompute(unittest.TestCase):
    def setUp(self):
        self.rows = (
            ('a', 2, 3, 4),
            (None, 3, 5, None),
            ('a', 2, 4, None),
            ('b', 3, 4, None)
        )

        self.number_type = NumberType()
        self.text_type = TextType()

        self.columns = (
            ('one', self.text_type),
            ('two', self.number_type),
            ('three', self.number_type),
            ('four', self.number_type)
        )

        self.table = Table(self.rows, self.columns)

    def test_compute(self):
        new_table = self.table.compute([
            ('test', Formula(self.number_type, lambda r: r['two'] + r['three']))
        ])

        self.assertIsNot(new_table, self.table)
        self.assertEqual(len(new_table.rows), 4)
        self.assertEqual(len(new_table.columns), 5)

        self.assertSequenceEqual(new_table.rows[0], ('a', 2, 3, 4, 5))
        self.assertSequenceEqual(new_table.columns['test'], (5, 8, 6, 7))
Exemplo n.º 22
0
class TestTableCompute(unittest.TestCase):
    def setUp(self):
        self.rows = (('a', 2, 3, 4), (None, 3, 5, None), ('a', 2, 4, None),
                     ('b', 3, 4, None))

        self.number_type = NumberType()
        self.text_type = TextType()

        self.columns = (('one', self.text_type), ('two', self.number_type),
                        ('three', self.number_type), ('four',
                                                      self.number_type))

        self.table = Table(self.rows, self.columns)

    def test_compute(self):
        new_table = self.table.compute([
            ('test', Formula(self.number_type,
                             lambda r: r['two'] + r['three']))
        ])

        self.assertIsNot(new_table, self.table)
        self.assertEqual(len(new_table.rows), 4)
        self.assertEqual(len(new_table.columns), 5)

        self.assertSequenceEqual(new_table.rows[0], ('a', 2, 3, 4, 5))
        self.assertSequenceEqual(new_table.columns['test'], (5, 8, 6, 7))
Exemplo n.º 23
0
    def test_change_timedeltas(self):
        rows = (('4:15', '8:18'), ('4h 2m', '2h'), ('4 weeks', '27 days'))

        timedelta_type = TimeDelta()

        column_names = ['one', 'two']
        column_types = [timedelta_type, timedelta_type]

        table = Table(rows, column_names, column_types)

        new_table = table.compute([('test', Change('one', 'two'))])

        self.assertIsNot(new_table, table)
        self.assertEqual(len(new_table.rows), 3)
        self.assertEqual(len(new_table.columns), 3)

        self.assertSequenceEqual(new_table.rows[0],
                                 (datetime.timedelta(minutes=4, seconds=15),
                                  datetime.timedelta(minutes=8, seconds=18),
                                  datetime.timedelta(minutes=4, seconds=3)))
        self.assertEqual(new_table.columns['test'][0],
                         datetime.timedelta(minutes=4, seconds=3))
        self.assertEqual(new_table.columns['test'][1],
                         datetime.timedelta(hours=-2, minutes=-2))
        self.assertEqual(new_table.columns['test'][2],
                         datetime.timedelta(days=-1))
Exemplo n.º 24
0
    def test_change_datetimes(self):
        rows = (('10/4/2015 4:43', '10/7/2015 4:50'),
                ('10/2/2015 12 PM', '9/28/2015 12 PM'), ('9/28/2015 12:00:00',
                                                         '9/1/2015 6 PM'))

        datetime_type = DateTime()

        column_names = ['one', 'two']
        column_types = [datetime_type, datetime_type]

        table = Table(rows, column_names, column_types)

        new_table = table.compute([('test', Change('one', 'two'))])

        self.assertIsNot(new_table, table)
        self.assertEqual(len(new_table.rows), 3)
        self.assertEqual(len(new_table.columns), 3)

        self.assertSequenceEqual(new_table.rows[0], (datetime.datetime(
            2015, 10, 4, 4, 43), datetime.datetime(
                2015, 10, 7, 4, 50), datetime.timedelta(days=3, minutes=7)))

        self.assertEqual(new_table.columns['test'][0],
                         datetime.timedelta(days=3, minutes=7))
        self.assertEqual(new_table.columns['test'][1],
                         datetime.timedelta(days=-4))
        self.assertEqual(new_table.columns['test'][2],
                         datetime.timedelta(days=-26, hours=-18))
Exemplo n.º 25
0
    def test_change_dates(self):
        rows = (('10/4/2015', '10/7/2015'), ('10/2/2015', '9/28/2015'),
                ('9/28/2015', '9/1/2015'))

        date_type = Date()

        column_names = ['one', 'two']
        column_types = [date_type, date_type]

        table = Table(rows, column_names, column_types)

        new_table = table.compute([('test', Change('one', 'two'))])

        self.assertIsNot(new_table, table)
        self.assertEqual(len(new_table.rows), 3)
        self.assertEqual(len(new_table.columns), 3)

        self.assertSequenceEqual(
            new_table.rows[0],
            (datetime.date(2015, 10, 4), datetime.date(
                2015, 10, 7), datetime.timedelta(days=3)))

        self.assertEqual(new_table.columns['test'][0],
                         datetime.timedelta(days=3))
        self.assertEqual(new_table.columns['test'][1],
                         datetime.timedelta(days=-4))
        self.assertEqual(new_table.columns['test'][2],
                         datetime.timedelta(days=-27))
Exemplo n.º 26
0
    def test_changed_invalid_types(self):
        rows = (
            (False, True),
            (True, False)
        )

        columns = (
            ('before', Boolean()),
            ('after', Boolean())
        )

        table = Table(rows, columns)

        with self.assertRaises(DataTypeError):
            table.compute([
                (Change('before', 'after'), 'test')
            ])
Exemplo n.º 27
0
    def test_change_mixed_types(self):
        rows = (
            ('1', '10/24/1978'),
            ('2', '11/13/1974')
        )

        columns = (
            ('number', Number()),
            ('date', Date())
        )

        table = Table(rows, columns)

        with self.assertRaises(ValueError):
            table.compute([
                ('test', Change('number', 'date'))
            ])
Exemplo n.º 28
0
    def test_change_mixed_types(self):
        rows = (
            ('1', '10/24/1978'),
            ('2', '11/13/1974')
        )

        columns = (
            ('number', Number()),
            ('date', Date())
        )

        table = Table(rows, columns)

        with self.assertRaises(ValueError):
            table.compute([
                (Change('number', 'date'), 'test')
            ])
Exemplo n.º 29
0
    def test_compute_with_row_names(self):
        table = Table(self.rows, self.column_names, self.column_types, row_names='three')

        new_table = table.compute([
            ('number', Formula(self.number_type, lambda r: r['two'] + r['three'])),
            ('text', Formula(self.text_type, lambda r: (r['one'] or '-') + six.text_type(r['three'])))
        ])

        self.assertRowNames(new_table, [3, 5, 4, 6])
Exemplo n.º 30
0
    def test_compute_with_row_names(self):
        table = Table(self.rows, self.column_names, self.column_types, row_names='three')

        new_table = table.compute([
            ('number', Formula(self.number_type, lambda r: r['two'] + r['three'])),
            ('text', Formula(self.text_type, lambda r: (r['one'] or '-') + six.text_type(r['three'])))
        ])

        self.assertRowNames(new_table, [3, 5, 4, 6])
Exemplo n.º 31
0
    def test_compute_with_row_names(self):
        table = Table(self.rows, self.columns, row_names='three')

        new_table = table.compute([
            (Formula(self.number_type, lambda r: r['two'] + r['three']), 'number'),
            (Formula(self.text_type, lambda r: (r['one'] or '-') + six.text_type(r['three'])), 'text')
        ])

        self.assertSequenceEqual(new_table.rows[0], ('a', 2, 3, 4, 5, 'a3'))
        self.assertSequenceEqual(new_table.row_names, (3, 5, 4, 6))
Exemplo n.º 32
0
    def test_compute_with_row_names(self):
        table = Table(self.rows, self.column_names, self.column_types, row_names='three')

        new_table = table.compute([
            (Formula(self.number_type, lambda r: r['two'] + r['three']), 'number'),
            (Formula(self.text_type, lambda r: (r['one'] or '-') + six.text_type(r['three'])), 'text')
        ])

        self.assertSequenceEqual(new_table.rows[0], ('a', 2, 3, 4, 5, 'a3'))
        self.assertSequenceEqual(new_table.row_names, (3, 5, 4, 6))
    def test_slug_column_name_sequence(self):
        rows = (('hello world', 2, 'Ab*c #e'), ('Ab*c #e', 2, 'He11O W0rld'),
                ('He11O W0rld', 3, 'hello world'))
        expected = [
            'hello_world_ab_c_e', 'ab_c_e_he11o_w0rld',
            'he11o_w0rld_hello_world'
        ]

        table1 = Table(rows, ['one', 'two', 'three'],
                       [self.text_type, self.number_type, self.text_type])
        table2 = table1.compute([('slugs', Slug(['one', 'three']))])

        self.assertSequenceEqual(table2.columns['slugs'], expected)
Exemplo n.º 34
0
    def test_slug_column_name_sequence(self):
        rows = (
            ('hello world', 2, 'Ab*c #e'),
            ('Ab*c #e', 2, 'He11O W0rld'),
            ('He11O W0rld', 3, 'hello world')
        )
        expected = ['hello-world-ab-c-e', 'ab-c-e-he11o-w0rld', 'he11o-w0rld-hello-world']

        table1 = Table(rows, ['one', 'two', 'three'], [self.text_type, self.number_type, self.text_type])
        table2 = table1.compute([
            ('slugs', Slug(['one', 'three']))
        ])

        self.assertSequenceEqual(table2.columns['slugs'], expected)
Exemplo n.º 35
0
    def test_compute_creates_rows(self):
        table = Table(self.rows, self.columns)
        table2 = table.compute([
            ('new2', Formula(self.number_type, lambda r: r['one']))
        ])
        table3 = table2.compute([
            ('new3', Formula(self.number_type, lambda r: r['one']))
        ])

        self.assertIsNot(table._data[0], table2._data[0])
        self.assertNotEqual(table._data[0], table2._data[0])
        self.assertIsNot(table2._data[0], table3._data[0])
        self.assertNotEqual(table2._data[0], table3._data[0])
        self.assertSequenceEqual(table._data[0], (1, 4, 'a'))
Exemplo n.º 36
0
    def test_compute_creates_rows(self):
        table = Table(self.rows, self.column_names, self.column_types)
        table2 = table.compute([
            (Formula(self.number_type, lambda r: r['one']), 'new2')
        ])
        table3 = table2.compute([
            (Formula(self.number_type, lambda r: r['one']), 'new3')
        ])

        self.assertIsNot(table.rows[0], table2.rows[0])
        self.assertNotEqual(table.rows[0], table2.rows[0])
        self.assertIsNot(table2.rows[0], table3.rows[0])
        self.assertNotEqual(table2.rows[0], table3.rows[0])
        self.assertSequenceEqual(table.rows[0], (1, 4, 'a'))
Exemplo n.º 37
0
    def test_compute_creates_rows(self):
        table = Table(self.rows, self.columns)
        table2 = table.compute([
            (Formula(self.number_type, lambda r: r['one']), 'new2')
        ])
        table3 = table2.compute([
            (Formula(self.number_type, lambda r: r['one']), 'new3')
        ])

        self.assertIsNot(table.rows[0], table2.rows[0])
        self.assertNotEqual(table.rows[0], table2.rows[0])
        self.assertIsNot(table2.rows[0], table3.rows[0])
        self.assertNotEqual(table2.rows[0], table3.rows[0])
        self.assertSequenceEqual(table.rows[0], (1, 4, 'a'))
Exemplo n.º 38
0
    def test_percentile_rank(self):
        rows = [(n, ) for n in range(1, 1001)]

        table = Table(rows, ['ints'], [self.number_type])
        new_table = table.compute([('percentiles', PercentileRank('ints'))])

        self.assertEqual(len(new_table.rows), 1000)
        self.assertEqual(len(new_table.columns), 2)

        self.assertSequenceEqual(new_table.rows[0], (1, 0))
        self.assertSequenceEqual(new_table.rows[50], (51, 5))
        self.assertSequenceEqual(new_table.rows[499], (500, 49))
        self.assertSequenceEqual(new_table.rows[500], (501, 50))
        self.assertSequenceEqual(new_table.rows[998], (999, 99))
        self.assertSequenceEqual(new_table.rows[999], (1000, 100))
Exemplo n.º 39
0
    def test_percentile_rank(self):
        rows = [(n,) for n in range(1, 1001)]

        table = Table(rows, ["ints"], [self.number_type])
        new_table = table.compute([("percentiles", PercentileRank("ints"))])

        self.assertEqual(len(new_table.rows), 1000)
        self.assertEqual(len(new_table.columns), 2)

        self.assertSequenceEqual(new_table.rows[0], (1, 0))
        self.assertSequenceEqual(new_table.rows[50], (51, 5))
        self.assertSequenceEqual(new_table.rows[499], (500, 49))
        self.assertSequenceEqual(new_table.rows[500], (501, 50))
        self.assertSequenceEqual(new_table.rows[998], (999, 99))
        self.assertSequenceEqual(new_table.rows[999], (1000, 100))
    def test_percent_zeros(self):
        column_names = ['label', 'value']
        rows = (('one', 25), ('two', 25), ('three', 0))
        new_table = Table(rows, column_names)
        new_table = new_table.compute([
            ('test', Percent('value')),
        ])

        def to_one_place(d):
            return d.quantize(Decimal('0.1'))

        self.assertEqual(to_one_place(new_table.columns['test'][0]),
                         Decimal('50.0'))
        self.assertEqual(to_one_place(new_table.columns['test'][1]),
                         Decimal('50.0'))
        self.assertEqual(to_one_place(new_table.columns['test'][2]),
                         Decimal('0.0'))
Exemplo n.º 41
0
    def test_percent_zeros(self):
        column_names = ['label', 'value']
        rows = (
            ('one', 25),
            ('two', 25),
            ('three', 0)
        )
        new_table = Table(rows, column_names)
        new_table = new_table.compute([
            ('test', Percent('value')),
        ])

        def to_one_place(d):
            return d.quantize(Decimal('0.1'))

        self.assertEqual(to_one_place(new_table.columns['test'][0]), Decimal('50.0'))
        self.assertEqual(to_one_place(new_table.columns['test'][1]), Decimal('50.0'))
        self.assertEqual(to_one_place(new_table.columns['test'][2]), Decimal('0.0'))
Exemplo n.º 42
0
    def test_percentile_rank(self):
        rows = [(n,) for n in range(1, 1001)]

        table = Table(rows, ['ints'], [self.number_type])
        new_table = table.compute([
            ('percentiles', PercentileRank('ints'))
        ])

        self.assertEqual(len(new_table.rows), 1000)
        self.assertEqual(len(new_table.columns), 2)

        self.assertSequenceEqual(new_table.rows[0], (1, 0))
        self.assertSequenceEqual(new_table.rows[50], (51, 5))
        self.assertSequenceEqual(new_table.rows[499], (500, 49))
        self.assertSequenceEqual(new_table.rows[500], (501, 50))
        self.assertSequenceEqual(new_table.rows[998], (999, 99))
        self.assertSequenceEqual(new_table.rows[999], (1000, 100))
        self.assertIsInstance(new_table.columns['percentiles'][0], Decimal)
        self.assertIsInstance(new_table.columns['percentiles'][-1], Decimal)
    def test_percent_total_override(self):
        new_table = self.table.compute([('test', Percent('two', 5))])

        def to_one_place(d):
            return d.quantize(Decimal('0.1'))

        self.assertEqual(to_one_place(new_table.columns['test'][0]),
                         Decimal('40.0'))
        self.assertEqual(to_one_place(new_table.columns['test'][1]),
                         Decimal('60.0'))
        self.assertEqual(to_one_place(new_table.columns['test'][2]),
                         Decimal('40.0'))
        self.assertEqual(to_one_place(new_table.columns['test'][3]),
                         Decimal('60.0'))

        with self.assertRaises(DataTypeError):
            new_table = self.table.compute([('test', Percent('two', 0))])
        with self.assertRaises(DataTypeError):
            new_table = self.table.compute([('test', Percent('two', -1))])
        with self.assertRaises(DataTypeError):
            zero_table = Table([[0]], ['zero'], [self.number_type])
            new_table = zero_table.compute([('test', Percent('zero'))])
Exemplo n.º 44
0
    def test_change_dates(self):
        rows = (("10/4/2015", "10/7/2015"), ("10/2/2015", "9/28/2015"), ("9/28/2015", "9/1/2015"))

        date_type = Date()

        column_names = ["one", "two"]
        column_types = [date_type, date_type]

        table = Table(rows, column_names, column_types)

        new_table = table.compute([("test", Change("one", "two"))])

        self.assertIsNot(new_table, table)
        self.assertEqual(len(new_table.rows), 3)
        self.assertEqual(len(new_table.columns), 3)

        self.assertSequenceEqual(
            new_table.rows[0], (datetime.date(2015, 10, 4), datetime.date(2015, 10, 7), datetime.timedelta(days=3))
        )

        self.assertEqual(new_table.columns["test"][0], datetime.timedelta(days=3))
        self.assertEqual(new_table.columns["test"][1], datetime.timedelta(days=-4))
        self.assertEqual(new_table.columns["test"][2], datetime.timedelta(days=-27))
Exemplo n.º 45
0
    def test_percent_total_override(self):
        new_table = self.table.compute([
            ('test', Percent('two', 5))
        ])

        def to_one_place(d):
            return d.quantize(Decimal('0.1'))

        self.assertEqual(to_one_place(new_table.columns['test'][0]), Decimal('40.0'))
        self.assertEqual(to_one_place(new_table.columns['test'][1]), Decimal('60.0'))
        self.assertEqual(to_one_place(new_table.columns['test'][2]), Decimal('40.0'))
        self.assertEqual(to_one_place(new_table.columns['test'][3]), Decimal('60.0'))

        with self.assertRaises(DataTypeError):
            new_table = self.table.compute([
                ('test', Percent('two', 0))
            ])
        with self.assertRaises(DataTypeError):
            new_table = self.table.compute([
                ('test', Percent('two', -1))
            ])
        with self.assertRaises(DataTypeError):
            zero_table = Table([[0]], ['zero'], [self.number_type])
            new_table = zero_table.compute([('test', Percent('zero'))])
Exemplo n.º 46
0
class TestCompute(AgateTestCase):
    def setUp(self):
        self.rows = (
            ('a', 2, 3, 4),
            (None, 3, 5, None),
            ('a', 2, 4, None),
            ('b', 3, 6, None)
        )

        self.number_type = Number()
        self.text_type = Text()

        self.column_names = [
            'one', 'two', 'three', 'four'
        ]
        self.column_types = [
            self.text_type, self.number_type, self.number_type, self.number_type
        ]

        self.table = Table(self.rows, self.column_names, self.column_types)

    def test_compute(self):
        new_table = self.table.compute([
            ('test', Formula(self.number_type, lambda r: r['two'] + r['three']))
        ])

        self.assertIsNot(new_table, self.table)
        self.assertColumnNames(new_table, ['one', 'two', 'three', 'four', 'test'])
        self.assertColumnTypes(new_table, [Text, Number, Number, Number, Number])

        self.assertSequenceEqual(new_table.rows[0], ('a', 2, 3, 4, 5))
        self.assertSequenceEqual(new_table.columns['test'], (5, 8, 6, 9))

    def test_compute_multiple(self):
        new_table = self.table.compute([
            ('number', Formula(self.number_type, lambda r: r['two'] + r['three'])),
            ('text', Formula(self.text_type, lambda r: (r['one'] or '-') + six.text_type(r['three'])))
        ])

        self.assertIsNot(new_table, self.table)
        self.assertColumnNames(new_table, ['one', 'two', 'three', 'four', 'number', 'text'])
        self.assertColumnTypes(new_table, [Text, Number, Number, Number, Number, Text])

        self.assertSequenceEqual(new_table.rows[0], ('a', 2, 3, 4, 5, 'a3'))
        self.assertSequenceEqual(new_table.columns['number'], (5, 8, 6, 9))
        self.assertSequenceEqual(new_table.columns['text'], ('a3', '-5', 'a4', 'b6'))

    def test_compute_with_row_names(self):
        table = Table(self.rows, self.column_names, self.column_types, row_names='three')

        new_table = table.compute([
            ('number', Formula(self.number_type, lambda r: r['two'] + r['three'])),
            ('text', Formula(self.text_type, lambda r: (r['one'] or '-') + six.text_type(r['three'])))
        ])

        self.assertRowNames(new_table, [3, 5, 4, 6])

    def test_compute_replace(self):
        new_table = self.table.compute([
            ('two', Formula(self.number_type, lambda r: r['two'] + r['three']))
        ], replace=True)

        self.assertIsNot(new_table, self.table)
        self.assertColumnNames(new_table, ['one', 'two', 'three', 'four'])
        self.assertColumnTypes(new_table, [Text, Number, Number, Number])

        self.assertSequenceEqual(new_table.rows[0], ('a', 5, 3, 4))
        self.assertSequenceEqual(new_table.columns['two'], (5, 8, 6, 9))

    def test_compute_replace_change_type(self):
        new_table = self.table.compute([
            ('two', Formula(self.text_type, lambda r: 'a'))
        ], replace=True)

        self.assertIsNot(new_table, self.table)
        self.assertColumnNames(new_table, ['one', 'two', 'three', 'four'])
        self.assertColumnTypes(new_table, [Text, Text, Number, Number])

        self.assertSequenceEqual(new_table.rows[0], ('a', 'a', 3, 4))
        self.assertSequenceEqual(new_table.columns['two'], ('a', 'a', 'a', 'a'))

    def test_compute_replace_partial(self):
        new_table = self.table.compute([
            ('two', Formula(self.number_type, lambda r: r['two'] + r['three'])),
            ('test', Formula(self.number_type, lambda r: 1))
        ], replace=True)

        self.assertIsNot(new_table, self.table)
        self.assertColumnNames(new_table, ['one', 'two', 'three', 'four', 'test'])
        self.assertColumnTypes(new_table, [Text, Number, Number, Number, Number])

        self.assertSequenceEqual(new_table.rows[0], ('a', 5, 3, 4, 1))
        self.assertSequenceEqual(new_table.columns['two'], (5, 8, 6, 9))
Exemplo n.º 47
0
class TestTableComputation(unittest.TestCase):
    def setUp(self):
        self.rows = (('a', 2, 3, 4), (None, 3, 5, None), ('a', 2, 4, None),
                     ('b', 3, 4, None))

        self.number_type = Number()
        self.text_type = Text()

        self.column_names = ['one', 'two', 'three', 'four']
        self.column_types = [
            self.text_type, self.number_type, self.number_type,
            self.number_type
        ]

        self.table = Table(self.rows, self.column_names, self.column_types)

    def test_formula(self):
        new_table = self.table.compute([
            ('test', Formula(self.number_type,
                             lambda r: r['two'] + r['three']))
        ])

        self.assertIsNot(new_table, self.table)
        self.assertEqual(len(new_table.rows), 4)
        self.assertEqual(len(new_table.columns), 5)

        self.assertSequenceEqual(
            new_table.rows[0],
            ('a', Decimal('2'), Decimal('3'), Decimal('4'), Decimal('5')))
        self.assertEqual(new_table.columns['test'][0], Decimal('5'))
        self.assertEqual(new_table.columns['test'][1], Decimal('8'))
        self.assertEqual(new_table.columns['test'][2], Decimal('6'))
        self.assertEqual(new_table.columns['test'][3], Decimal('7'))

    def test_formula_invalid(self):
        with self.assertRaises(CastError):
            new_table = self.table.compute([('test',
                                             Formula(self.number_type,
                                                     lambda r: r['one']))])

    def test_formula_no_validate(self):
        new_table = self.table.compute([('test',
                                         Formula(self.number_type,
                                                 lambda r: r['one'],
                                                 validate=False))])

        # Now everything is screwed up
        self.assertSequenceEqual(
            new_table.rows[0],
            ('a', Decimal('2'), Decimal('3'), Decimal('4'), 'a'))
        self.assertEqual(new_table.columns['test'][0], 'a')

    def test_change(self):
        new_table = self.table.compute([('test', Change('two', 'three'))])

        self.assertIsNot(new_table, self.table)
        self.assertEqual(len(new_table.rows), 4)
        self.assertEqual(len(new_table.columns), 5)

        self.assertSequenceEqual(
            new_table.rows[0],
            ('a', Decimal('2'), Decimal('3'), Decimal('4'), Decimal('1')))
        self.assertEqual(new_table.columns['test'][0], Decimal('1'))
        self.assertEqual(new_table.columns['test'][1], Decimal('2'))
        self.assertEqual(new_table.columns['test'][2], Decimal('2'))
        self.assertEqual(new_table.columns['test'][3], Decimal('1'))

    def test_change_mixed_types(self):
        rows = (('1', '10/24/1978'), ('2', '11/13/1974'))

        column_names = ['number', 'date']
        column_types = [Number(), Date()]

        table = Table(rows, column_names, column_types)

        with self.assertRaises(ValueError):
            table.compute([('test', Change('number', 'date'))])

    def test_changed_invalid_types(self):
        rows = ((False, True), (True, False))

        column_names = ['before', 'after']
        column_types = [Boolean(), Boolean()]

        table = Table(rows, column_names, column_types)

        with self.assertRaises(DataTypeError):
            table.compute([('test', Change('before', 'after'))])

    def test_change_nulls(self):
        warnings.simplefilter('error')

        with self.assertRaises(NullCalculationWarning):
            new_table = self.table.compute([('test', Change('three', 'four'))])

        with self.assertRaises(NullCalculationWarning):
            new_table = self.table.compute([('test', Change('four', 'three'))])

        warnings.simplefilter('ignore')

        new_table = self.table.compute([('test', Change('three', 'four'))])

        self.assertIsNot(new_table, self.table)
        self.assertEqual(len(new_table.rows), 4)
        self.assertEqual(len(new_table.columns), 5)

        self.assertSequenceEqual(
            new_table.rows[0],
            ('a', Decimal('2'), Decimal('3'), Decimal('4'), Decimal('1')))
        self.assertEqual(new_table.columns['test'][0], Decimal('1'))
        self.assertEqual(new_table.columns['test'][1], None)
        self.assertEqual(new_table.columns['test'][2], None)
        self.assertEqual(new_table.columns['test'][3], None)

    def test_percent_change(self):
        new_table = self.table.compute([('test', PercentChange('two',
                                                               'three'))])

        self.assertIsNot(new_table, self.table)
        self.assertEqual(len(new_table.rows), 4)
        self.assertEqual(len(new_table.columns), 5)

        to_one_place = lambda d: d.quantize(Decimal('0.1'))

        self.assertSequenceEqual(
            new_table.rows[0],
            ('a', Decimal('2'), Decimal('3'), Decimal('4'), Decimal('50.0')))
        self.assertEqual(to_one_place(new_table.columns['test'][0]),
                         Decimal('50.0'))
        self.assertEqual(to_one_place(new_table.columns['test'][1]),
                         Decimal('66.7'))
        self.assertEqual(to_one_place(new_table.columns['test'][2]),
                         Decimal('100.0'))
        self.assertEqual(to_one_place(new_table.columns['test'][3]),
                         Decimal('33.3'))

    def test_percent_change_invalid_columns(self):
        with self.assertRaises(DataTypeError):
            new_table = self.table.compute([('test',
                                             PercentChange('one', 'three'))])

    def test_rank_number(self):
        new_table = self.table.compute([('rank', Rank('two'))])

        self.assertEqual(len(new_table.rows), 4)
        self.assertEqual(len(new_table.columns), 5)
        self.assertSequenceEqual(new_table.columns['rank'], (1, 3, 1, 3))

    def test_rank_number_reverse(self):
        new_table = self.table.compute([('rank', Rank('two', reverse=True))])

        self.assertEqual(len(new_table.rows), 4)
        self.assertEqual(len(new_table.columns), 5)
        self.assertSequenceEqual(new_table.columns['rank'], (3, 1, 3, 1))

    def test_rank_number_key(self):
        new_table = self.table.compute([
            ('rank', Rank('two', comparer=lambda x, y: int(y - x)))
        ])

        self.assertEqual(len(new_table.rows), 4)
        self.assertEqual(len(new_table.columns), 5)
        self.assertSequenceEqual(new_table.columns['rank'], (3, 1, 3, 1))

    def test_rank_number_reverse_key(self):
        new_table = self.table.compute([('rank',
                                         Rank('two',
                                              comparer=lambda x, y: int(y - x),
                                              reverse=True))])

        self.assertEqual(len(new_table.rows), 4)
        self.assertEqual(len(new_table.columns), 5)
        self.assertSequenceEqual(new_table.columns['rank'], (1, 3, 1, 3))

    def test_rank_text(self):
        new_table = self.table.compute([('rank', Rank('one'))])

        self.assertEqual(len(new_table.rows), 4)
        self.assertEqual(len(new_table.columns), 5)
        self.assertSequenceEqual(new_table.columns['rank'], (1, 4, 1, 3))

    def test_percentile_rank(self):
        rows = [(n, ) for n in range(1, 1001)]

        table = Table(rows, ['ints'], [self.number_type])
        new_table = table.compute([('percentiles', PercentileRank('ints'))])

        self.assertEqual(len(new_table.rows), 1000)
        self.assertEqual(len(new_table.columns), 2)

        self.assertSequenceEqual(new_table.rows[0], (1, 0))
        self.assertSequenceEqual(new_table.rows[50], (51, 5))
        self.assertSequenceEqual(new_table.rows[499], (500, 49))
        self.assertSequenceEqual(new_table.rows[500], (501, 50))
        self.assertSequenceEqual(new_table.rows[998], (999, 99))
        self.assertSequenceEqual(new_table.rows[999], (1000, 100))
Exemplo n.º 48
0
class TestTableComputation(unittest.TestCase):
    def setUp(self):
        self.rows = (
            ('a', 2, 3, 4),
            (None, 3, 5, None),
            ('a', 2, 4, None),
            ('b', 3, 4, None)
        )

        self.number_type = Number()
        self.text_type = Text()

        self.column_names = [
            'one', 'two', 'three', 'four'
        ]
        self.column_types = [
            self.text_type, self.number_type, self.number_type, self.number_type
        ]

        self.table = Table(self.rows, self.column_names, self.column_types)

    def test_formula(self):
        new_table = self.table.compute([
            ('test', Formula(self.number_type, lambda r: r['two'] + r['three']))
        ])

        self.assertIsNot(new_table, self.table)
        self.assertEqual(len(new_table.rows), 4)
        self.assertEqual(len(new_table.columns), 5)

        self.assertSequenceEqual(new_table.rows[0], ('a', Decimal('2'), Decimal('3'), Decimal('4'), Decimal('5')))
        self.assertEqual(new_table.columns['test'][0], Decimal('5'))
        self.assertEqual(new_table.columns['test'][1], Decimal('8'))
        self.assertEqual(new_table.columns['test'][2], Decimal('6'))
        self.assertEqual(new_table.columns['test'][3], Decimal('7'))

    def test_formula_invalid(self):
        with self.assertRaises(CastError):
            new_table = self.table.compute([  # noqa
                ('test', Formula(self.number_type, lambda r: r['one']))
            ])

    def test_formula_no_validate(self):
        new_table = self.table.compute([
            ('test', Formula(self.number_type, lambda r: r['one'], cast=False))
        ])

        # Now everything is screwed up
        self.assertSequenceEqual(new_table.rows[0], ('a', Decimal('2'), Decimal('3'), Decimal('4'), 'a'))
        self.assertEqual(new_table.columns['test'][0], 'a')

    def test_change(self):
        new_table = self.table.compute([
            ('test', Change('two', 'three'))
        ])

        self.assertIsNot(new_table, self.table)
        self.assertEqual(len(new_table.rows), 4)
        self.assertEqual(len(new_table.columns), 5)

        self.assertSequenceEqual(new_table.rows[0], ('a', Decimal('2'), Decimal('3'), Decimal('4'), Decimal('1')))
        self.assertEqual(new_table.columns['test'][0], Decimal('1'))
        self.assertEqual(new_table.columns['test'][1], Decimal('2'))
        self.assertEqual(new_table.columns['test'][2], Decimal('2'))
        self.assertEqual(new_table.columns['test'][3], Decimal('1'))

    def test_change_mixed_types(self):
        rows = (
            ('1', '10/24/1978'),
            ('2', '11/13/1974')
        )

        column_names = ['number', 'date']
        column_types = [Number(), Date()]

        table = Table(rows, column_names, column_types)

        with self.assertRaises(DataTypeError):
            table.compute([
                ('test', Change('number', 'date'))
            ])

    def test_changed_invalid_types(self):
        rows = (
            (False, True),
            (True, False)
        )

        column_names = ['before', 'after']
        column_types = [Boolean(), Boolean()]

        table = Table(rows, column_names, column_types)

        with self.assertRaises(DataTypeError):
            table.compute([
                ('test', Change('before', 'after'))
            ])

    def test_change_nulls(self):
        warnings.simplefilter('error')

        with self.assertRaises(NullCalculationWarning):
            new_table = self.table.compute([
                ('test', Change('three', 'four'))
            ])

        with self.assertRaises(NullCalculationWarning):
            new_table = self.table.compute([
                ('test', Change('four', 'three'))
            ])

        warnings.simplefilter('ignore')

        new_table = self.table.compute([
            ('test', Change('three', 'four'))
        ])

        self.assertIsNot(new_table, self.table)
        self.assertEqual(len(new_table.rows), 4)
        self.assertEqual(len(new_table.columns), 5)

        self.assertSequenceEqual(new_table.rows[0], ('a', Decimal('2'), Decimal('3'), Decimal('4'), Decimal('1')))
        self.assertEqual(new_table.columns['test'][0], Decimal('1'))
        self.assertEqual(new_table.columns['test'][1], None)
        self.assertEqual(new_table.columns['test'][2], None)
        self.assertEqual(new_table.columns['test'][3], None)

    def test_percent(self):
        new_table = self.table.compute([
            ('test', Percent('two'))
        ])

        self.assertIsNot(new_table, self.table)
        self.assertEqual(len(new_table.rows), 4)
        self.assertEqual(len(new_table.columns), 5)

        def to_one_place(d):
            return d.quantize(Decimal('0.1'))

        self.assertSequenceEqual(
            new_table.rows[0],
            ('a', Decimal('2'), Decimal('3'), Decimal('4'), Decimal('20.0'))
        )
        self.assertEqual(to_one_place(new_table.columns['test'][0]), Decimal('20.0'))
        self.assertEqual(to_one_place(new_table.columns['test'][1]), Decimal('30.0'))
        self.assertEqual(to_one_place(new_table.columns['test'][2]), Decimal('20.0'))
        self.assertEqual(to_one_place(new_table.columns['test'][3]), Decimal('30.0'))

    def test_percent_total_override(self):
        new_table = self.table.compute([
            ('test', Percent('two', 5))
        ])

        def to_one_place(d):
            return d.quantize(Decimal('0.1'))

        self.assertEqual(to_one_place(new_table.columns['test'][0]), Decimal('40.0'))
        self.assertEqual(to_one_place(new_table.columns['test'][1]), Decimal('60.0'))
        self.assertEqual(to_one_place(new_table.columns['test'][2]), Decimal('40.0'))
        self.assertEqual(to_one_place(new_table.columns['test'][3]), Decimal('60.0'))

        with self.assertRaises(DataTypeError):
            new_table = self.table.compute([
                ('test', Percent('two', 0))
            ])
        with self.assertRaises(DataTypeError):
            new_table = self.table.compute([
                ('test', Percent('two', -1))
            ])
        with self.assertRaises(DataTypeError):
            zero_table = Table([[0]], ['zero'], [self.number_type])
            new_table = zero_table.compute([('test', Percent('zero'))])

    def test_percent_zeros(self):
        column_names = ['label', 'value']
        rows = (
            ('one', 25),
            ('two', 25),
            ('three', 0)
        )
        new_table = Table(rows, column_names)
        new_table = new_table.compute([
            ('test', Percent('value')),
        ])

        def to_one_place(d):
            return d.quantize(Decimal('0.1'))

        self.assertEqual(to_one_place(new_table.columns['test'][0]), Decimal('50.0'))
        self.assertEqual(to_one_place(new_table.columns['test'][1]), Decimal('50.0'))
        self.assertEqual(to_one_place(new_table.columns['test'][2]), Decimal('0.0'))

    def test_percent_nulls(self):
        new_table = self.table.compute([
            ('test', Percent('four'))
        ])

        def to_one_place(d):
            return d.quantize(Decimal('0.1'))

        self.assertEqual(
            to_one_place(new_table.columns['test'][0]),
            Decimal('100.0')
        )
        self.assertEqual(new_table.columns['test'][1], None)
        self.assertEqual(new_table.columns['test'][2], None)
        self.assertEqual(new_table.columns['test'][3], None)

    def test_percent_change(self):
        new_table = self.table.compute([
            ('test', PercentChange('two', 'three'))
        ])

        self.assertIsNot(new_table, self.table)
        self.assertEqual(len(new_table.rows), 4)
        self.assertEqual(len(new_table.columns), 5)

        def to_one_place(d):
            return d.quantize(Decimal('0.1'))

        self.assertSequenceEqual(new_table.rows[0], ('a', Decimal('2'), Decimal('3'), Decimal('4'), Decimal('50.0')))
        self.assertEqual(to_one_place(new_table.columns['test'][0]), Decimal('50.0'))
        self.assertEqual(to_one_place(new_table.columns['test'][1]), Decimal('66.7'))
        self.assertEqual(to_one_place(new_table.columns['test'][2]), Decimal('100.0'))
        self.assertEqual(to_one_place(new_table.columns['test'][3]), Decimal('33.3'))

    def test_percent_change_invalid_columns(self):
        with self.assertRaises(DataTypeError):
            new_table = self.table.compute([
                ('test', PercentChange('one', 'three'))
            ])

        with self.assertRaises(DataTypeError):
            new_table = self.table.compute([  # noqa
                ('test', PercentChange('three', 'one'))
            ])

    def test_rank_number(self):
        new_table = self.table.compute([
            ('rank', Rank('two'))
        ])

        self.assertEqual(len(new_table.rows), 4)
        self.assertEqual(len(new_table.columns), 5)
        self.assertSequenceEqual(new_table.columns['rank'], (1, 3, 1, 3))
        self.assertIsInstance(new_table.columns['rank'][0], Decimal)

    def test_rank_number_reverse(self):
        new_table = self.table.compute([
            ('rank', Rank('two', reverse=True))
        ])

        self.assertEqual(len(new_table.rows), 4)
        self.assertEqual(len(new_table.columns), 5)
        self.assertSequenceEqual(new_table.columns['rank'], (3, 1, 3, 1))

    def test_rank_number_key(self):
        new_table = self.table.compute([
            ('rank', Rank('two', comparer=lambda x, y: int(y - x)))
        ])

        self.assertEqual(len(new_table.rows), 4)
        self.assertEqual(len(new_table.columns), 5)
        self.assertSequenceEqual(new_table.columns['rank'], (3, 1, 3, 1))

    def test_rank_number_reverse_key(self):
        new_table = self.table.compute([
            ('rank', Rank('two', comparer=lambda x, y: int(y - x), reverse=True))
        ])

        self.assertEqual(len(new_table.rows), 4)
        self.assertEqual(len(new_table.columns), 5)
        self.assertSequenceEqual(new_table.columns['rank'], (1, 3, 1, 3))

    def test_rank_text(self):
        new_table = self.table.compute([
            ('rank', Rank('one'))
        ])

        self.assertEqual(len(new_table.rows), 4)
        self.assertEqual(len(new_table.columns), 5)
        self.assertSequenceEqual(new_table.columns['rank'], (1, 4, 1, 3))

    def test_percentile_rank(self):
        rows = [(n,) for n in range(1, 1001)]

        table = Table(rows, ['ints'], [self.number_type])
        new_table = table.compute([
            ('percentiles', PercentileRank('ints'))
        ])

        self.assertEqual(len(new_table.rows), 1000)
        self.assertEqual(len(new_table.columns), 2)

        self.assertSequenceEqual(new_table.rows[0], (1, 0))
        self.assertSequenceEqual(new_table.rows[50], (51, 5))
        self.assertSequenceEqual(new_table.rows[499], (500, 49))
        self.assertSequenceEqual(new_table.rows[500], (501, 50))
        self.assertSequenceEqual(new_table.rows[998], (999, 99))
        self.assertSequenceEqual(new_table.rows[999], (1000, 100))
        self.assertIsInstance(new_table.columns['percentiles'][0], Decimal)
        self.assertIsInstance(new_table.columns['percentiles'][-1], Decimal)

    def test_percentile_rank_invalid_types(self):
        with self.assertRaises(DataTypeError):
            self.table.compute([
                ('test', PercentileRank('one'))
            ])
Exemplo n.º 49
0
class TestTableComputation(unittest.TestCase):
    def setUp(self):
        self.rows = (("a", 2, 3, 4), (None, 3, 5, None), ("a", 2, 4, None), ("b", 3, 4, None))

        self.number_type = Number()
        self.text_type = Text()

        self.column_names = ["one", "two", "three", "four"]
        self.column_types = [self.text_type, self.number_type, self.number_type, self.number_type]

        self.table = Table(self.rows, self.column_names, self.column_types)

    def test_change(self):
        new_table = self.table.compute([("test", Change("two", "three"))])

        self.assertIsNot(new_table, self.table)
        self.assertEqual(len(new_table.rows), 4)
        self.assertEqual(len(new_table.columns), 5)

        self.assertSequenceEqual(new_table.rows[0], ("a", Decimal("2"), Decimal("3"), Decimal("4"), Decimal("1")))
        self.assertEqual(new_table.columns["test"][0], Decimal("1"))
        self.assertEqual(new_table.columns["test"][1], Decimal("2"))
        self.assertEqual(new_table.columns["test"][2], Decimal("2"))
        self.assertEqual(new_table.columns["test"][3], Decimal("1"))

    def test_change_mixed_types(self):
        rows = (("1", "10/24/1978"), ("2", "11/13/1974"))

        column_names = ["number", "date"]
        column_types = [Number(), Date()]

        table = Table(rows, column_names, column_types)

        with self.assertRaises(ValueError):
            table.compute([("test", Change("number", "date"))])

    def test_changed_invalid_types(self):
        rows = ((False, True), (True, False))

        column_names = ["before", "after"]
        column_types = [Boolean(), Boolean()]

        table = Table(rows, column_names, column_types)

        with self.assertRaises(DataTypeError):
            table.compute([("test", Change("before", "after"))])

    def test_change_nulls(self):
        warnings.simplefilter("error")

        with self.assertRaises(NullCalculationWarning):
            new_table = self.table.compute([("test", Change("three", "four"))])

        with self.assertRaises(NullCalculationWarning):
            new_table = self.table.compute([("test", Change("four", "three"))])

        warnings.simplefilter("ignore")

        new_table = self.table.compute([("test", Change("three", "four"))])

        self.assertIsNot(new_table, self.table)
        self.assertEqual(len(new_table.rows), 4)
        self.assertEqual(len(new_table.columns), 5)

        self.assertSequenceEqual(new_table.rows[0], ("a", Decimal("2"), Decimal("3"), Decimal("4"), Decimal("1")))
        self.assertEqual(new_table.columns["test"][0], Decimal("1"))
        self.assertEqual(new_table.columns["test"][1], None)
        self.assertEqual(new_table.columns["test"][2], None)
        self.assertEqual(new_table.columns["test"][3], None)

    def test_percent_change(self):
        new_table = self.table.compute([("test", PercentChange("two", "three"))])

        self.assertIsNot(new_table, self.table)
        self.assertEqual(len(new_table.rows), 4)
        self.assertEqual(len(new_table.columns), 5)

        to_one_place = lambda d: d.quantize(Decimal("0.1"))

        self.assertSequenceEqual(new_table.rows[0], ("a", Decimal("2"), Decimal("3"), Decimal("4"), Decimal("50.0")))
        self.assertEqual(to_one_place(new_table.columns["test"][0]), Decimal("50.0"))
        self.assertEqual(to_one_place(new_table.columns["test"][1]), Decimal("66.7"))
        self.assertEqual(to_one_place(new_table.columns["test"][2]), Decimal("100.0"))
        self.assertEqual(to_one_place(new_table.columns["test"][3]), Decimal("33.3"))

    def test_percent_change_invalid_columns(self):
        with self.assertRaises(DataTypeError):
            new_table = self.table.compute([("test", PercentChange("one", "three"))])

    def test_rank_number(self):
        new_table = self.table.compute([("rank", Rank("two"))])

        self.assertEqual(len(new_table.rows), 4)
        self.assertEqual(len(new_table.columns), 5)
        self.assertSequenceEqual(new_table.columns["rank"], (1, 3, 1, 3))

    def test_rank_number_reverse(self):
        new_table = self.table.compute([("rank", Rank("two", reverse=True))])

        self.assertEqual(len(new_table.rows), 4)
        self.assertEqual(len(new_table.columns), 5)
        self.assertSequenceEqual(new_table.columns["rank"], (3, 1, 3, 1))

    def test_rank_number_key(self):
        new_table = self.table.compute([("rank", Rank("two", comparer=lambda x, y: int(y - x)))])

        self.assertEqual(len(new_table.rows), 4)
        self.assertEqual(len(new_table.columns), 5)
        self.assertSequenceEqual(new_table.columns["rank"], (3, 1, 3, 1))

    def test_rank_number_reverse_key(self):
        new_table = self.table.compute([("rank", Rank("two", comparer=lambda x, y: int(y - x), reverse=True))])

        self.assertEqual(len(new_table.rows), 4)
        self.assertEqual(len(new_table.columns), 5)
        self.assertSequenceEqual(new_table.columns["rank"], (1, 3, 1, 3))

    def test_rank_text(self):
        new_table = self.table.compute([("rank", Rank("one"))])

        self.assertEqual(len(new_table.rows), 4)
        self.assertEqual(len(new_table.columns), 5)
        self.assertSequenceEqual(new_table.columns["rank"], (1, 4, 1, 3))

    def test_percentile_rank(self):
        rows = [(n,) for n in range(1, 1001)]

        table = Table(rows, ["ints"], [self.number_type])
        new_table = table.compute([("percentiles", PercentileRank("ints"))])

        self.assertEqual(len(new_table.rows), 1000)
        self.assertEqual(len(new_table.columns), 2)

        self.assertSequenceEqual(new_table.rows[0], (1, 0))
        self.assertSequenceEqual(new_table.rows[50], (51, 5))
        self.assertSequenceEqual(new_table.rows[499], (500, 49))
        self.assertSequenceEqual(new_table.rows[500], (501, 50))
        self.assertSequenceEqual(new_table.rows[998], (999, 99))
        self.assertSequenceEqual(new_table.rows[999], (1000, 100))
Exemplo n.º 50
0
class TestTableComputation(unittest.TestCase):
    def setUp(self):
        self.rows = (
            ('a', 2, 3, 4),
            (None, 3, 5, None),
            ('a', 2, 4, None),
            ('b', 3, 4, None)
        )

        self.number_type = NumberType()
        self.text_type = TextType()

        self.columns = (
            ('one', self.text_type),
            ('two', self.number_type),
            ('three', self.number_type),
            ('four', self.number_type),
        )

        self.table = Table(self.rows, self.columns)

    def test_change(self):
        new_table = self.table.compute([
            ('test', Change('two', 'three'))
        ])

        self.assertIsNot(new_table, self.table)
        self.assertEqual(len(new_table.rows), 4)
        self.assertEqual(len(new_table.columns), 5)

        to_one_place = lambda d: d.quantize(Decimal('0.1'))

        self.assertSequenceEqual(new_table.rows[0], ('a', Decimal('2'), Decimal('3'), Decimal('4'), Decimal('1')))
        self.assertEqual(new_table.columns['test'][0], Decimal('1'))
        self.assertEqual(new_table.columns['test'][1], Decimal('2'))
        self.assertEqual(new_table.columns['test'][2], Decimal('2'))
        self.assertEqual(new_table.columns['test'][3], Decimal('1'))

    def test_percent_change(self):
        new_table = self.table.compute([
            ('test', PercentChange('two', 'three'))
        ])

        self.assertIsNot(new_table, self.table)
        self.assertEqual(len(new_table.rows), 4)
        self.assertEqual(len(new_table.columns), 5)

        to_one_place = lambda d: d.quantize(Decimal('0.1'))

        self.assertSequenceEqual(new_table.rows[0], ('a', Decimal('2'), Decimal('3'), Decimal('4'), Decimal('50.0')))
        self.assertEqual(to_one_place(new_table.columns['test'][0]), Decimal('50.0'))
        self.assertEqual(to_one_place(new_table.columns['test'][1]), Decimal('66.7'))
        self.assertEqual(to_one_place(new_table.columns['test'][2]), Decimal('100.0'))
        self.assertEqual(to_one_place(new_table.columns['test'][3]), Decimal('33.3'))

    def test_percent_change_invalid_columns(self):
        with self.assertRaises(UnsupportedComputationError):
            new_table = self.table.compute([
                ('test', PercentChange('one', 'three'))
            ])

    def test_z_scores(self):
        new_table = self.table.compute([
            ('z-scores', ZScores('two'))
        ])

        self.assertEqual(len(new_table.rows), 4)
        self.assertEqual(len(new_table.columns), 5)

        self.assertSequenceEqual(new_table.rows[0], ('a', 2, 3, 4, -1))
        self.assertSequenceEqual(new_table.rows[1], (None, 3, 5, None, 1))
        self.assertSequenceEqual(new_table.rows[2], ('a', 2, 4, None, -1))
        self.assertSequenceEqual(new_table.rows[3], ('b', 3, 4, None, 1))

        self.assertSequenceEqual(new_table.columns['z-scores'],(-1,1,-1,1))

    def test_zscores_invalid_column(self):
        with self.assertRaises(UnsupportedComputationError):
            new_table = self.table.compute([
                ('test', ZScores('one'))
            ])

    def test_rank_number(self):
        new_table = self.table.compute([
            ('rank', Rank('two'))
        ])

        self.assertEqual(len(new_table.rows), 4)
        self.assertEqual(len(new_table.columns), 5)

        self.assertSequenceEqual(new_table.rows[0], ('a', 2, 3, 4, 1))
        self.assertSequenceEqual(new_table.rows[1], (None, 3, 5, None, 3))
        self.assertSequenceEqual(new_table.rows[2], ('a', 2, 4, None, 1))
        self.assertSequenceEqual(new_table.rows[3], ('b', 3, 4, None, 3))

        self.assertSequenceEqual(new_table.columns['rank'], (1, 3, 1, 3))

    def test_rank_text(self):
        new_table = self.table.compute([
            ('rank', Rank('one'))
        ])

        self.assertEqual(len(new_table.rows), 4)
        self.assertEqual(len(new_table.columns), 5)

        self.assertSequenceEqual(new_table.rows[0], ('a', 2, 3, 4, 1))
        self.assertSequenceEqual(new_table.rows[1], (None, 3, 5, None, 4))
        self.assertSequenceEqual(new_table.rows[2], ('a', 2, 4, None, 1))
        self.assertSequenceEqual(new_table.rows[3], ('b', 3, 4, None, 3))

        self.assertSequenceEqual(new_table.columns['rank'], (1, 4, 1, 3))

    def test_rank_column_name(self):
        new_table = self.table.compute([
            ('rank', Rank('two'))
        ])

        self.assertEqual(len(new_table.rows), 4)
        self.assertEqual(len(new_table.columns), 5)

        self.assertSequenceEqual(new_table.rows[0], ('a', 2, 3, 4, 1))
        self.assertSequenceEqual(new_table.rows[1], (None, 3, 5, None, 3))
        self.assertSequenceEqual(new_table.rows[2], ('a', 2, 4, None, 1))
        self.assertSequenceEqual(new_table.rows[3], ('b', 3, 4, None, 3))

        self.assertSequenceEqual(new_table.columns['rank'], (1, 3, 1, 3))

    def test_percentile_rank(self):
        rows = [(n,) for n in range(1, 1001)]

        table = Table(rows, (('ints', self.number_type),))
        new_table = table.compute([
            ('percentiles', PercentileRank('ints'))
        ])

        self.assertEqual(len(new_table.rows), 1000)
        self.assertEqual(len(new_table.columns), 2)

        self.assertSequenceEqual(new_table.rows[0], (1, 0))
        self.assertSequenceEqual(new_table.rows[50], (51, 5))
        self.assertSequenceEqual(new_table.rows[499], (500, 49))
        self.assertSequenceEqual(new_table.rows[500], (501, 50))
        self.assertSequenceEqual(new_table.rows[998], (999, 99))
        self.assertSequenceEqual(new_table.rows[999], (1000, 100))
class TestTableComputation(unittest.TestCase):
    def setUp(self):
        self.rows = (('a', 2, 3, 4), (None, 3, 5, None), ('a', 2, 4, None),
                     ('b', 3, 4, None))

        self.number_type = Number()
        self.text_type = Text()

        self.column_names = ['one', 'two', 'three', 'four']
        self.column_types = [
            self.text_type, self.number_type, self.number_type,
            self.number_type
        ]

        self.table = Table(self.rows, self.column_names, self.column_types)

    def test_formula(self):
        new_table = self.table.compute([
            ('test', Formula(self.number_type,
                             lambda r: r['two'] + r['three']))
        ])

        self.assertIsNot(new_table, self.table)
        self.assertEqual(len(new_table.rows), 4)
        self.assertEqual(len(new_table.columns), 5)

        self.assertSequenceEqual(
            new_table.rows[0],
            ('a', Decimal('2'), Decimal('3'), Decimal('4'), Decimal('5')))
        self.assertEqual(new_table.columns['test'][0], Decimal('5'))
        self.assertEqual(new_table.columns['test'][1], Decimal('8'))
        self.assertEqual(new_table.columns['test'][2], Decimal('6'))
        self.assertEqual(new_table.columns['test'][3], Decimal('7'))

    def test_formula_invalid(self):
        with self.assertRaises(CastError):
            new_table = self.table.compute([  # noqa
                ('test', Formula(self.number_type, lambda r: r['one']))
            ])

    def test_formula_no_validate(self):
        new_table = self.table.compute([('test',
                                         Formula(self.number_type,
                                                 lambda r: r['one'],
                                                 cast=False))])

        # Now everything is screwed up
        self.assertSequenceEqual(
            new_table.rows[0],
            ('a', Decimal('2'), Decimal('3'), Decimal('4'), 'a'))
        self.assertEqual(new_table.columns['test'][0], 'a')

    def test_change(self):
        new_table = self.table.compute([('test', Change('two', 'three'))])

        self.assertIsNot(new_table, self.table)
        self.assertEqual(len(new_table.rows), 4)
        self.assertEqual(len(new_table.columns), 5)

        self.assertSequenceEqual(
            new_table.rows[0],
            ('a', Decimal('2'), Decimal('3'), Decimal('4'), Decimal('1')))
        self.assertEqual(new_table.columns['test'][0], Decimal('1'))
        self.assertEqual(new_table.columns['test'][1], Decimal('2'))
        self.assertEqual(new_table.columns['test'][2], Decimal('2'))
        self.assertEqual(new_table.columns['test'][3], Decimal('1'))

    def test_change_mixed_types(self):
        rows = (('1', '10/24/1978'), ('2', '11/13/1974'))

        column_names = ['number', 'date']
        column_types = [Number(), Date()]

        table = Table(rows, column_names, column_types)

        with self.assertRaises(DataTypeError):
            table.compute([('test', Change('number', 'date'))])

    def test_changed_invalid_types(self):
        rows = ((False, True), (True, False))

        column_names = ['before', 'after']
        column_types = [Boolean(), Boolean()]

        table = Table(rows, column_names, column_types)

        with self.assertRaises(DataTypeError):
            table.compute([('test', Change('before', 'after'))])

    def test_change_nulls(self):
        with self.assertWarns(NullCalculationWarning):
            new_table = self.table.compute([('test', Change('three', 'four'))])

        with self.assertWarns(NullCalculationWarning):
            new_table = self.table.compute([('test', Change('four', 'three'))])

        warnings.simplefilter('ignore')

        try:
            new_table = self.table.compute([('test', Change('three', 'four'))])
        finally:
            warnings.resetwarnings()

        self.assertIsNot(new_table, self.table)
        self.assertEqual(len(new_table.rows), 4)
        self.assertEqual(len(new_table.columns), 5)

        self.assertSequenceEqual(
            new_table.rows[0],
            ('a', Decimal('2'), Decimal('3'), Decimal('4'), Decimal('1')))
        self.assertEqual(new_table.columns['test'][0], Decimal('1'))
        self.assertEqual(new_table.columns['test'][1], None)
        self.assertEqual(new_table.columns['test'][2], None)
        self.assertEqual(new_table.columns['test'][3], None)

    def test_percent(self):
        new_table = self.table.compute([('test', Percent('two'))])

        self.assertIsNot(new_table, self.table)
        self.assertEqual(len(new_table.rows), 4)
        self.assertEqual(len(new_table.columns), 5)

        def to_one_place(d):
            return d.quantize(Decimal('0.1'))

        self.assertSequenceEqual(
            new_table.rows[0],
            ('a', Decimal('2'), Decimal('3'), Decimal('4'), Decimal('20.0')))
        self.assertEqual(to_one_place(new_table.columns['test'][0]),
                         Decimal('20.0'))
        self.assertEqual(to_one_place(new_table.columns['test'][1]),
                         Decimal('30.0'))
        self.assertEqual(to_one_place(new_table.columns['test'][2]),
                         Decimal('20.0'))
        self.assertEqual(to_one_place(new_table.columns['test'][3]),
                         Decimal('30.0'))

    def test_percent_total_override(self):
        new_table = self.table.compute([('test', Percent('two', 5))])

        def to_one_place(d):
            return d.quantize(Decimal('0.1'))

        self.assertEqual(to_one_place(new_table.columns['test'][0]),
                         Decimal('40.0'))
        self.assertEqual(to_one_place(new_table.columns['test'][1]),
                         Decimal('60.0'))
        self.assertEqual(to_one_place(new_table.columns['test'][2]),
                         Decimal('40.0'))
        self.assertEqual(to_one_place(new_table.columns['test'][3]),
                         Decimal('60.0'))

        with self.assertRaises(DataTypeError):
            new_table = self.table.compute([('test', Percent('two', 0))])
        with self.assertRaises(DataTypeError):
            new_table = self.table.compute([('test', Percent('two', -1))])
        with self.assertRaises(DataTypeError):
            zero_table = Table([[0]], ['zero'], [self.number_type])
            new_table = zero_table.compute([('test', Percent('zero'))])

    def test_percent_zeros(self):
        column_names = ['label', 'value']
        rows = (('one', 25), ('two', 25), ('three', 0))
        new_table = Table(rows, column_names)
        new_table = new_table.compute([
            ('test', Percent('value')),
        ])

        def to_one_place(d):
            return d.quantize(Decimal('0.1'))

        self.assertEqual(to_one_place(new_table.columns['test'][0]),
                         Decimal('50.0'))
        self.assertEqual(to_one_place(new_table.columns['test'][1]),
                         Decimal('50.0'))
        self.assertEqual(to_one_place(new_table.columns['test'][2]),
                         Decimal('0.0'))

    def test_percent_nulls(self):
        warnings.simplefilter('ignore')

        try:
            new_table = self.table.compute([('test', Percent('four'))])
        finally:
            warnings.resetwarnings()

        def to_one_place(d):
            return d.quantize(Decimal('0.1'))

        self.assertEqual(to_one_place(new_table.columns['test'][0]),
                         Decimal('100.0'))
        self.assertEqual(new_table.columns['test'][1], None)
        self.assertEqual(new_table.columns['test'][2], None)
        self.assertEqual(new_table.columns['test'][3], None)

    def test_percent_change(self):
        new_table = self.table.compute([('test', PercentChange('two',
                                                               'three'))])

        self.assertIsNot(new_table, self.table)
        self.assertEqual(len(new_table.rows), 4)
        self.assertEqual(len(new_table.columns), 5)

        def to_one_place(d):
            return d.quantize(Decimal('0.1'))

        self.assertSequenceEqual(
            new_table.rows[0],
            ('a', Decimal('2'), Decimal('3'), Decimal('4'), Decimal('50.0')))
        self.assertEqual(to_one_place(new_table.columns['test'][0]),
                         Decimal('50.0'))
        self.assertEqual(to_one_place(new_table.columns['test'][1]),
                         Decimal('66.7'))
        self.assertEqual(to_one_place(new_table.columns['test'][2]),
                         Decimal('100.0'))
        self.assertEqual(to_one_place(new_table.columns['test'][3]),
                         Decimal('33.3'))

    def test_percent_change_invalid_columns(self):
        with self.assertRaises(DataTypeError):
            new_table = self.table.compute([('test',
                                             PercentChange('one', 'three'))])

        with self.assertRaises(DataTypeError):
            new_table = self.table.compute([  # noqa
                ('test', PercentChange('three', 'one'))
            ])

    def test_percent_change_nulls(self):
        with self.assertWarns(NullCalculationWarning):
            new_table = self.table.compute([('test',
                                             PercentChange('three', 'four'))])

        with self.assertWarns(NullCalculationWarning):
            new_table = self.table.compute([('test',
                                             PercentChange('four', 'three'))])

        warnings.simplefilter('ignore')

        try:
            new_table = self.table.compute([('test',
                                             PercentChange('three', 'four'))])
        finally:
            warnings.resetwarnings()

        self.assertIsNot(new_table, self.table)
        self.assertEqual(len(new_table.rows), 4)
        self.assertEqual(len(new_table.columns), 5)

        def to_one_place(d):
            return d.quantize(Decimal('0.1'))

        self.assertSequenceEqual(new_table.rows[2],
                                 ('a', Decimal('2'), Decimal('4'), None, None))
        self.assertEqual(to_one_place(new_table.columns['test'][0]),
                         Decimal('33.3'))
        self.assertEqual(new_table.columns['test'][1], None)
        self.assertEqual(new_table.columns['test'][2], None)
        self.assertEqual(new_table.columns['test'][3], None)

    def test_rank_number(self):
        new_table = self.table.compute([('rank', Rank('two'))])

        self.assertEqual(len(new_table.rows), 4)
        self.assertEqual(len(new_table.columns), 5)
        self.assertSequenceEqual(new_table.columns['rank'], (1, 3, 1, 3))
        self.assertIsInstance(new_table.columns['rank'][0], Decimal)

    def test_rank_number_reverse(self):
        new_table = self.table.compute([('rank', Rank('two', reverse=True))])

        self.assertEqual(len(new_table.rows), 4)
        self.assertEqual(len(new_table.columns), 5)
        self.assertSequenceEqual(new_table.columns['rank'], (3, 1, 3, 1))

    def test_rank_number_key(self):
        new_table = self.table.compute([
            ('rank', Rank('two', comparer=lambda x, y: int(y - x)))
        ])

        self.assertEqual(len(new_table.rows), 4)
        self.assertEqual(len(new_table.columns), 5)
        self.assertSequenceEqual(new_table.columns['rank'], (3, 1, 3, 1))

    def test_rank_number_reverse_key(self):
        new_table = self.table.compute([('rank',
                                         Rank('two',
                                              comparer=lambda x, y: int(y - x),
                                              reverse=True))])

        self.assertEqual(len(new_table.rows), 4)
        self.assertEqual(len(new_table.columns), 5)
        self.assertSequenceEqual(new_table.columns['rank'], (1, 3, 1, 3))

    def test_rank_text(self):
        new_table = self.table.compute([('rank', Rank('one'))])

        self.assertEqual(len(new_table.rows), 4)
        self.assertEqual(len(new_table.columns), 5)
        self.assertSequenceEqual(new_table.columns['rank'], (1, 4, 1, 3))

    def test_percentile_rank(self):
        rows = [(n, ) for n in range(1, 1001)]

        table = Table(rows, ['ints'], [self.number_type])
        new_table = table.compute([('percentiles', PercentileRank('ints'))])

        self.assertEqual(len(new_table.rows), 1000)
        self.assertEqual(len(new_table.columns), 2)

        self.assertSequenceEqual(new_table.rows[0], (1, 0))
        self.assertSequenceEqual(new_table.rows[50], (51, 5))
        self.assertSequenceEqual(new_table.rows[499], (500, 49))
        self.assertSequenceEqual(new_table.rows[500], (501, 50))
        self.assertSequenceEqual(new_table.rows[998], (999, 99))
        self.assertSequenceEqual(new_table.rows[999], (1000, 100))
        self.assertIsInstance(new_table.columns['percentiles'][0], Decimal)
        self.assertIsInstance(new_table.columns['percentiles'][-1], Decimal)

    def test_percentile_rank_invalid_types(self):
        with self.assertRaises(DataTypeError):
            self.table.compute([('test', PercentileRank('one'))])

    def test_slug(self):
        rows = (('hello world', 2), ('Ab*c #e', 2), ('He11O W0rld', 3))
        expected = ['hello_world', 'ab_c_e', 'he11o_w0rld']

        table = Table(rows, ['one', 'two'],
                      [self.text_type, self.number_type]).compute([
                          ('slugs', Slug('one'))
                      ])

        self.assertSequenceEqual(table.columns['slugs'], expected)

    def test_slug_column_name_sequence(self):
        rows = (('hello world', 2, 'Ab*c #e'), ('Ab*c #e', 2, 'He11O W0rld'),
                ('He11O W0rld', 3, 'hello world'))
        expected = [
            'hello_world_ab_c_e', 'ab_c_e_he11o_w0rld',
            'he11o_w0rld_hello_world'
        ]

        table1 = Table(rows, ['one', 'two', 'three'],
                       [self.text_type, self.number_type, self.text_type])
        table2 = table1.compute([('slugs', Slug(['one', 'three']))])

        self.assertSequenceEqual(table2.columns['slugs'], expected)

    def test_slug_ensure_unique(self):
        rows = (('hello world', 2), ('Ab*c #e', 2), ('He11O W0rld', 3),
                ('HellO WOrld ', 3))
        expected = ['hello_world', 'ab_c_e', 'he11o_w0rld', 'hello_world_2']

        table = Table(rows, ['one', 'two'],
                      [self.text_type, self.number_type]).compute([
                          ('slugs', Slug('one', ensure_unique=True))
                      ])

        self.assertSequenceEqual(table.columns['slugs'], expected)

    def test_slug_contains_null_error(self):
        with self.assertRaises(ValueError):
            self.table.compute([('slugs', Slug('one', ensure_unique=True))])