Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions rows/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,5 +58,9 @@
except ImportError:
pass

try:
from rows.plugins._pandas import import_from_pandas, export_to_pandas
except ImportError:
pass

__version__ = '0.2.0-dev'
60 changes: 60 additions & 0 deletions rows/plugins/_pandas.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
# coding: utf-8

# Copyright 2014-2015 Álvaro Justen <https://github.com/turicas/rows/>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.

import datetime

import pandas

from rows.plugins.utils import create_table

DATE_FORMAT = "%Y-%m-%d %H:%M:%S"

def import_from_pandas(data_frame, *args, **kwargs):
meta = {'imported_from': 'pandas', 'filename': 'DataFrame', }
return create_table(_dataframe_generator(data_frame), meta=meta, *args,
**kwargs)

def _dataframe_generator(data_frame):
yield list(data_frame)

for _, row in data_frame.iterrows():
yield dataframe_row_to_list(row)

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

May use dataframe.itertuples.

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

May use dataframe.itertuples.


def dataframe_row_to_list(row):
result = []
for element_index, element in enumerate(row):
#Problem importing pandas.tslib.Timestamp or pandas.Timestamp
if isinstance(element, pandas.tslib.Timestamp):
date_string = element.strftime(DATE_FORMAT)
if date_string.endswith("00:00:00"):
value = datetime.datetime.strptime(date_string,
DATE_FORMAT).date()
else:
value = element.to_datetime()
result.append(value)
return result


def export_to_pandas(table_obj):
data_frame = pandas.DataFrame(_generator_table(table_obj),
columns=table_obj.field_names)

return data_frame

def _generator_table(table_obj):
for row in table_obj:
yield list(row)
3 changes: 2 additions & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,8 @@
'html': ['lxml'], # apt: libxslt-dev libxml2-dev
'ods': ['lxml'],
'xls': ['xlrd', 'xlwt'],
'xlsx': ['openpyxl'], }
'xlsx': ['openpyxl'],
'pandas': ['pandas'], }
EXTRA_REQUIREMENTS['all'] = sum(EXTRA_REQUIREMENTS.values(), [])
INSTALL_REQUIREMENTS = EXTRA_REQUIREMENTS['csv']
LONG_DESCRIPTION = '''
Expand Down
56 changes: 56 additions & 0 deletions tests/tests_plugin_pandas.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
# coding: utf-8

# Copyright 2014-2015 Álvaro Justen <https://github.com/turicas/rows/>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
import unittest
import mock

import pandas

import rows.plugins._pandas
import rows.plugins.csv
import utils

class PluginPandasTestCase(utils.RowsTestMixIn, unittest.TestCase):

plugin_name = 'pandas'
data_frame = pandas.DataFrame([[1, 2, 3, 4], [5, 6, 7, 8]],
columns=['A', 'B', 'C', 'D'])

def test_imports(self):
self.assertIs(rows.import_from_pandas,
rows.plugins._pandas.import_from_pandas)

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing export_to_pandas.


@mock.patch('rows.plugins._pandas.create_table')
def test_import_from_pandas_uses_create_table(self, mocked_create_table):
mocked_create_table.return_value = 101
kwargs = {'encoding': 'test', 'some_key': 123, 'other': 456, }
result = rows.import_from_pandas(self.data_frame, **kwargs)
self.assertTrue(mocked_create_table.called)
self.assertEqual(mocked_create_table.call_count, 1)
self.assertEqual(result, 101)

call = mocked_create_table.call_args
kwargs['meta'] = {'imported_from': 'pandas', 'filename': 'DataFrame'}

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since it was not imported from a file, filename key should be None.

self.assertEqual(call[1], kwargs)

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You need to assert the call[0] to verify if import_from_pandas called create_table with the proper header + table rows.


@mock.patch('rows.plugins._pandas.pandas.DataFrame')
def test_export_to_pandas_uses_data_frame(self, mocked_data_frame):
mocked_data_frame.return_value = 101
result = rows.plugins._pandas.export_to_pandas(utils.table)
self.assertTrue(mocked_data_frame.called)
self.assertTrue(mocked_data_frame.call_count, 1)
self.assertEqual(result, 101)