From 1427be2901cb53c52d60a1438492b01cee39b867 Mon Sep 17 00:00:00 2001 From: Luca Beltrame Date: Mon, 15 Nov 2010 08:59:49 +0100 Subject: [PATCH 1/5] Support for row and column stacking. Unit-tested. --- tablib/core.py | 53 ++++++++++++++++++++++++++++++++++++++++++++++++++ test_tablib.py | 38 ++++++++++++++++++++++++++++++++++++ 2 files changed, 91 insertions(+) diff --git a/tablib/core.py b/tablib/core.py index 23026a2..47d2e13 100644 --- a/tablib/core.py +++ b/tablib/core.py @@ -535,6 +535,59 @@ class Dataset(object): _dset.append(row=row_data) return _dset + + def row_stack(self, other): + + """Stack two :class:`Dataset` instances together by + joining them at the row level, and return a new + combined ``Dataset`` instance.""" + + if not isinstance(other, Dataset): + return + + if self.width != other.width: + raise InvalidDimensions + + # Copy the source data + _dset = copy(self) + + rows_to_stack = [row for row in _dset._data] + other_rows = [row for row in other._data] + + rows_to_stack.extend(other_rows) + _dset._data = rows_to_stack + + return _dset + + def column_stack(self, other): + + """Stack two :class:`Dataset` instances together by + joining at the column level, and return a new + combined ``Dataset`` instance. Requires headers + to be set.""" + + if not isinstance(other, Dataset): + return + + if not self.headers or not other.headers: + raise HeadersNeeded + + if self.height != other.height: + raise InvalidDimensions + + new_headers = self.headers + other.headers + + _dset = Dataset() + + for column in self.headers: + _dset.append(col=self[column]) + + for column in other.headers: + _dset.append(col=other[column]) + + _dset.headers = new_headers + + return _dset def wipe(self): """Removes all content and headers from the :class:`Dataset` object.""" diff --git a/test_tablib.py b/test_tablib.py index f203179..126ee84 100755 --- a/test_tablib.py +++ b/test_tablib.py @@ -3,6 +3,7 @@ """Tests for Tablib.""" +from copy import copy import unittest import tablib @@ -364,7 +365,44 @@ class TablibTestCase(unittest.TestCase): ("last_name","Adams", "Washington", "Jefferson")) self.assertEqual(second_row, ("gpa",90, 67, 50)) + + def test_row_stacking(self): + """Row stacking.""" + + to_join = tablib.Dataset(headers=self.founders.headers) + + for row in self.founders: + to_join.append(row=row) + + row_stacked = self.founders.row_stack(to_join) + + for column in row_stacked.headers: + + original_data = self.founders[column] + expected_data = original_data + original_data + self.assertEqual(row_stacked[column], expected_data) + + def test_column_stacking(self): + + """Column stacking""" + + to_join = tablib.Dataset(headers=self.founders.headers) + + for row in self.founders: + to_join.append(row=row) + + column_stacked = self.founders.column_stack(to_join) + + for index, row in enumerate(column_stacked): + + original_data = self.founders[index] + expected_data = original_data + original_data + self.assertEqual(row, expected_data) + + self.assertEqual(column_stacked[0], + ("John", "Adams", 90, "John", "Adams", 90)) + def test_wipe(self): """Purge a dataset.""" From 36bbe2726bb014188241164956273096ac795c05 Mon Sep 17 00:00:00 2001 From: Luca Beltrame Date: Mon, 15 Nov 2010 09:00:57 +0100 Subject: [PATCH 2/5] Remove unneded import --- test_tablib.py | 1 - 1 file changed, 1 deletion(-) diff --git a/test_tablib.py b/test_tablib.py index 126ee84..e9ef5af 100755 --- a/test_tablib.py +++ b/test_tablib.py @@ -3,7 +3,6 @@ """Tests for Tablib.""" -from copy import copy import unittest import tablib From a2990d5852206ac0ab11fa87bb256b3924871169 Mon Sep 17 00:00:00 2001 From: Kenneth Reitz Date: Wed, 17 Nov 2010 20:01:31 -0500 Subject: [PATCH 3/5] Change stacking method names. --- tablib/core.py | 10 +++++----- test_tablib.py | 5 +++-- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/tablib/core.py b/tablib/core.py index 4f86b41..26923ea 100644 --- a/tablib/core.py +++ b/tablib/core.py @@ -547,8 +547,8 @@ class Dataset(object): _dset.append(row=row_data) return _dset - - def row_stack(self, other): + + def stack_rows(self, other): """Stack two :class:`Dataset` instances together by joining them at the row level, and return a new @@ -562,16 +562,16 @@ class Dataset(object): # Copy the source data _dset = copy(self) - + rows_to_stack = [row for row in _dset._data] other_rows = [row for row in other._data] rows_to_stack.extend(other_rows) _dset._data = rows_to_stack - + return _dset - def column_stack(self, other): + def stack_columns(self, other): """Stack two :class:`Dataset` instances together by joining at the column level, and return a new diff --git a/test_tablib.py b/test_tablib.py index e9ef5af..40e83ce 100755 --- a/test_tablib.py +++ b/test_tablib.py @@ -374,7 +374,7 @@ class TablibTestCase(unittest.TestCase): for row in self.founders: to_join.append(row=row) - row_stacked = self.founders.row_stack(to_join) + row_stacked = self.founders.stack_rows(to_join) for column in row_stacked.headers: @@ -391,7 +391,7 @@ class TablibTestCase(unittest.TestCase): for row in self.founders: to_join.append(row=row) - column_stacked = self.founders.column_stack(to_join) + column_stacked = self.founders.stack_columns(to_join) for index, row in enumerate(column_stacked): @@ -402,6 +402,7 @@ class TablibTestCase(unittest.TestCase): self.assertEqual(column_stacked[0], ("John", "Adams", 90, "John", "Adams", 90)) + def test_wipe(self): """Purge a dataset.""" From 196edb82ccbfbca2fe6696f69973384cf570c7f9 Mon Sep 17 00:00:00 2001 From: Kenneth Reitz Date: Wed, 17 Nov 2010 20:02:08 -0500 Subject: [PATCH 4/5] trailing whitespae --- test_tablib.py | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/test_tablib.py b/test_tablib.py index 40e83ce..8e2454f 100755 --- a/test_tablib.py +++ b/test_tablib.py @@ -194,7 +194,7 @@ class TablibTestCase(unittest.TestCase): data.tsv data.xls - + def test_book_export_no_exceptions(self): """Test that varoius exports don't error out.""" @@ -245,7 +245,7 @@ class TablibTestCase(unittest.TestCase): self.assertEqual(_yaml, data.yaml) - + def test_yaml_import_book(self): """Generate and import YAML book serialization.""" data.append(self.john) @@ -258,7 +258,7 @@ class TablibTestCase(unittest.TestCase): book.yaml = _yaml self.assertEqual(_yaml, book.yaml) - + def test_csv_import_set(self): """Generate and import CSV set serialization.""" @@ -286,7 +286,7 @@ class TablibTestCase(unittest.TestCase): def test_csv_format_detect(self): """Test CSV format detection.""" - + _csv = ( '1,2,3\n' '4,5,6\n' @@ -295,13 +295,13 @@ class TablibTestCase(unittest.TestCase): _bunk = ( '¡¡¡¡¡¡¡¡£™∞¢£§∞§¶•¶ª∞¶•ªº••ª–º§•†•§º¶•†¥ª–º•§ƒø¥¨©πƒø†ˆ¥ç©¨√øˆ¥≈†ƒ¥ç©ø¨çˆ¥ƒçø¶' ) - + self.assertTrue(tablib.formats.csv.detect(_csv)) self.assertFalse(tablib.formats.csv.detect(_bunk)) def test_tsv_format_detect(self): """Test TSV format detection.""" - + _tsv = ( '1\t2\t3\n' '4\t5\t6\n' @@ -310,7 +310,7 @@ class TablibTestCase(unittest.TestCase): _bunk = ( '¡¡¡¡¡¡¡¡£™∞¢£§∞§¶•¶ª∞¶•ªº••ª–º§•†•§º¶•†¥ª–º•§ƒø¥¨©πƒø†ˆ¥ç©¨√øˆ¥≈†ƒ¥ç©ø¨çˆ¥ƒçø¶' ) - + self.assertTrue(tablib.formats.tsv.detect(_tsv)) self.assertFalse(tablib.formats.tsv.detect(_bunk)) @@ -357,23 +357,23 @@ class TablibTestCase(unittest.TestCase): transposed_founders = self.founders.transpose() first_row = transposed_founders[0] second_row = transposed_founders[1] - + self.assertEqual(transposed_founders.headers, ["first_name","John", "George", "Thomas"]) self.assertEqual(first_row, ("last_name","Adams", "Washington", "Jefferson")) self.assertEqual(second_row, ("gpa",90, 67, 50)) - + def test_row_stacking(self): """Row stacking.""" to_join = tablib.Dataset(headers=self.founders.headers) - + for row in self.founders: to_join.append(row=row) - + row_stacked = self.founders.stack_rows(to_join) for column in row_stacked.headers: @@ -387,7 +387,7 @@ class TablibTestCase(unittest.TestCase): """Column stacking""" to_join = tablib.Dataset(headers=self.founders.headers) - + for row in self.founders: to_join.append(row=row) @@ -401,7 +401,7 @@ class TablibTestCase(unittest.TestCase): self.assertEqual(column_stacked[0], ("John", "Adams", 90, "John", "Adams", 90)) - + def test_wipe(self): """Purge a dataset.""" From 1a9aee928970ecaaba40529fd2def1e47059b828 Mon Sep 17 00:00:00 2001 From: Kenneth Reitz Date: Wed, 17 Nov 2010 20:48:50 -0500 Subject: [PATCH 5/5] Column stacking only requires headers if headers exist. --- tablib/core.py | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/tablib/core.py b/tablib/core.py index 26923ea..7d3c94c 100644 --- a/tablib/core.py +++ b/tablib/core.py @@ -548,11 +548,11 @@ class Dataset(object): return _dset - def stack_rows(self, other): + def stack_rows(self, other): """Stack two :class:`Dataset` instances together by - joining them at the row level, and return a new - combined ``Dataset`` instance.""" + joining at the row level, and return new combined + ``Dataset`` instance.""" if not isinstance(other, Dataset): return @@ -571,23 +571,27 @@ class Dataset(object): return _dset - def stack_columns(self, other): + def stack_columns(self, other): """Stack two :class:`Dataset` instances together by joining at the column level, and return a new - combined ``Dataset`` instance. Requires headers - to be set.""" + combined ``Dataset`` instance. If either ``Dataset`` + has headers set, than the other must as well.""" if not isinstance(other, Dataset): return - if not self.headers or not other.headers: - raise HeadersNeeded + if self.headers or other.headers: + if not self.headers or not other.headers: + raise HeadersNeeded if self.height != other.height: raise InvalidDimensions - new_headers = self.headers + other.headers + try: + new_headers = self.headers + other.headers + except TypeError: + new_headers = None _dset = Dataset()