import unittest
import tempfile
import pathlib
import datetime
import warnings

from IPython.testing.globalipapp import start_ipython, get_ipython

import pandas.util.testing as tm
from pandas.core.frame import DataFrame
from pandas.core.series import Series
from pandas import read_excel

import pytest

ip = get_ipython()
ip.magic('load_ext excelify')

class TestMagicExportImport(unittest.TestCase):

    def setUp(self):
        self.tempexcel = tempfile.NamedTemporaryFile(suffix='.xlsx')

    def test_series(self):
        series = Series()
        excel_name = self.tempexcel.name
        ip.run_line_magic('excel', 'series -f {filepath}'.format(filepath=excel_name))
        loaded_series = read_excel(excel_name, squeeze=True, dtype=series.dtype)
        tm.assert_series_equal(series, loaded_series, check_names=False)

    def test_dataframe(self):
        df = DataFrame()
        excel_name = self.tempexcel.name
        ip.run_line_magic('excel', 'df -f {filepath}'.format(filepath=excel_name))
        loaded_df = read_excel(excel_name, dtype=df.dtypes)
        tm.assert_frame_equal(df, loaded_df, check_names=False)

    def test_sheet_name(self):
        series = Series()
        excel_name = self.tempexcel.name
        sheetname = 'test_sheet_name'
        ip.run_line_magic('excel', 'series -f {filepath} -s {sheetname}'.format(filepath=excel_name, sheetname=sheetname))
        loaded_excel = read_excel(excel_name, sheet_name=None)
        assert 'test_sheet_name' in loaded_excel

    def test_all_pandas_objects(self):
        df1 = DataFrame()
        df2 = DataFrame()
        series1 = Series()
        series2 = Series()
        pandas_objects = [(name, obj) for (name, obj) in locals().items()
                          if isinstance(obj, (DataFrame, Series))]
        excel_name = self.tempexcel.name
        ip.run_line_magic('excel_all', '-f {filepath}'.format(filepath=excel_name))
        for (name, obj) in pandas_objects:
            if isinstance(obj, Series):
                loaded_data = read_excel(excel_name, sheet_name=name, squeeze=True, dtype=obj.dtype)
                tm.assert_series_equal(obj, loaded_data, check_names=False)
            elif isinstance(obj, DataFrame):
                loaded_data = read_excel(excel_name, sheet_name=name, dtype=obj.dtypes)
                tm.assert_frame_equal(obj, loaded_data, check_names=False)

    def test_sheet_timestamp(self):
        series = Series()
        excel_name = self.tempexcel.name
        ip.run_line_magic('excel', 'series -f {filepath}'.format(filepath=excel_name))
        loaded_excel = read_excel(excel_name, sheet_name=None)
        sheet_names = list(loaded_excel.keys())
        for sheet in sheet_names:
            _, date_string = sheet.split('_')
            saved_date = datetime.datetime.strptime(date_string, "%Y%m%d-%H%M%S")
            load_to_read = datetime.datetime.now() - saved_date
            # there is probably a better way to test this
            assert load_to_read.seconds < 10

    def test_all_long_name(self):
        with warnings.catch_warnings(record=True) as w:
            warnings.simplefilter("always")
            locals().update({'a' * 33 : Series()})
            excel_name = self.tempexcel.name
            ip.run_line_magic('excel_all', '-f {filepath}'.format(filepath=excel_name))
            assert len(w) == 1
            assert issubclass(w[-1].category, UserWarning)
            assert "truncated" in str(w[-1].message)

    def test_long_name_provided(self):
        with warnings.catch_warnings(record=True) as w:
            series = Series()
            excel_name = self.tempexcel.name
            longsheet = 'a' * 33
            ip.run_line_magic('excel', 'series -f {filepath} -s {longsheet}'.format(filepath=excel_name, longsheet=longsheet))
            assert len(w) == 1
            assert issubclass(w[-1].category, UserWarning)
            assert "truncated" in str(w[-1].message)

    def test_long_name_default(self):
        with warnings.catch_warnings(record=True) as w:
            warnings.simplefilter("always")
            longsheet = 'a' * 33
            locals().update({longsheet : Series()})
            excel_name = self.tempexcel.name
            ip.run_line_magic('excel', '{longsheet} -f {filepath}'.format(longsheet=longsheet, filepath=excel_name))
            assert len(w) == 1
            assert issubclass(w[-1].category, UserWarning)
            assert "truncated" in str(w[-1].message)

    def tearDown(self):
        self.tempexcel.close()


def test_filename():
    series = Series()
    ip.run_line_magic('excel', 'series')
    excel_name = list(pathlib.Path().glob('series_*.xlsx'))[0]
    assert excel_name.exists()
    excel_name.unlink()

def test_all_filename():
    series = Series()
    df = DataFrame()
    ip.run_line_magic('excel_all', '')
    excel_name = list(pathlib.Path().glob('all_data_*.xlsx'))[0]
    assert excel_name.exists()
    excel_name.unlink()


@pytest.fixture
def no_extension_file():
    file = tempfile.NamedTemporaryFile()
    yield file
    file.close()

def test_filepath_append(no_extension_file):
    series = Series()
    excel_name = no_extension_file.name
    ip.run_line_magic('excel', 'series -f {filepath}'.format(filepath=excel_name))
    exported_filepath = pathlib.PurePath(excel_name + '.xlsx')
    assert exported_filepath.suffix == '.xlsx'
    
def test_all_filepath_append(no_extension_file):
    series = Series()
    df = DataFrame()
    excel_name = no_extension_file.name
    ip.run_line_magic('excel_all', '-f {filepath}'.format(filepath=excel_name))
    exported_filepath = pathlib.Path(excel_name + '.xlsx')
    exported_filepath = pathlib.PurePath(excel_name + '.xlsx')
    assert exported_filepath.suffix == '.xlsx'

def test_no_object():
    with pytest.raises(NameError):
        ip.run_line_magic('excel', 'nonexistantobject')

def test_non_pandas_object():
    integer = 3
    with pytest.raises(TypeError):
        ip.run_line_magic('excel', 'integer')

    string = 'string'
    with pytest.raises(TypeError):
        ip.run_line_magic('excel', 'string')

def test_all_no_objects():
    with pytest.raises(RuntimeError):
        ip.run_line_magic('excel_all', '')

def test_all_too_many_objects():
    # this seems like a bad idea...
    for i in range(102):
        locals().update({'series' + str(i) : Series()})
    with pytest.raises(RuntimeError):
        ip.run_line_magic('excel_all', '')


[((16, 5, 16, 18), 'IPython.testing.globalipapp.get_ipython', 'get_ipython', ({}, {}), '()', False, 'from IPython.testing.globalipapp import start_ipython, get_ipython\n'), ((112, 13, 112, 21), 'pandas.core.series.Series', 'Series', ({}, {}), '()', False, 'from pandas.core.series import Series\n'), ((119, 13, 119, 21), 'pandas.core.series.Series', 'Series', ({}, {}), '()', False, 'from pandas.core.series import Series\n'), ((120, 9, 120, 20), 'pandas.core.frame.DataFrame', 'DataFrame', ({}, {}), '()', False, 'from pandas.core.frame import DataFrame\n'), ((129, 11, 129, 40), 'tempfile.NamedTemporaryFile', 'tempfile.NamedTemporaryFile', ({}, {}), '()', False, 'import tempfile\n'), ((134, 13, 134, 21), 'pandas.core.series.Series', 'Series', ({}, {}), '()', False, 'from pandas.core.series import Series\n'), ((137, 24, 137, 62), 'pathlib.PurePath', 'pathlib.PurePath', ({(137, 41, 137, 61): "excel_name + '.xlsx'"}, {}), "(excel_name + '.xlsx')", False, 'import pathlib\n'), ((141, 13, 141, 21), 'pandas.core.series.Series', 'Series', ({}, {}), '()', False, 'from pandas.core.series import Series\n'), ((142, 9, 142, 20), 'pandas.core.frame.DataFrame', 'DataFrame', ({}, {}), '()', False, 'from pandas.core.frame import DataFrame\n'), ((145, 24, 145, 58), 'pathlib.Path', 'pathlib.Path', ({(145, 37, 145, 57): "excel_name + '.xlsx'"}, {}), "(excel_name + '.xlsx')", False, 'import pathlib\n'), ((146, 24, 146, 62), 'pathlib.PurePath', 'pathlib.PurePath', ({(146, 41, 146, 61): "excel_name + '.xlsx'"}, {}), "(excel_name + '.xlsx')", False, 'import pathlib\n'), ((22, 25, 22, 68), 'tempfile.NamedTemporaryFile', 'tempfile.NamedTemporaryFile', (), '', False, 'import tempfile\n'), ((25, 17, 25, 25), 'pandas.core.series.Series', 'Series', ({}, {}), '()', False, 'from pandas.core.series import Series\n'), ((28, 24, 28, 80), 'pandas.read_excel', 'read_excel', (), '', False, 'from pandas import read_excel\n'), ((29, 8, 29, 72), 'pandas.util.testing.assert_series_equal', 'tm.assert_series_equal', (), '', True, 'import pandas.util.testing as tm\n'), ((32, 13, 32, 24), 'pandas.core.frame.DataFrame', 'DataFrame', ({}, {}), '()', False, 'from pandas.core.frame import DataFrame\n'), ((35, 20, 35, 59), 'pandas.read_excel', 'read_excel', (), '', False, 'from pandas import read_excel\n'), ((36, 8, 36, 63), 'pandas.util.testing.assert_frame_equal', 'tm.assert_frame_equal', (), '', True, 'import pandas.util.testing as tm\n'), ((39, 17, 39, 25), 'pandas.core.series.Series', 'Series', ({}, {}), '()', False, 'from pandas.core.series import Series\n'), ((43, 23, 43, 62), 'pandas.read_excel', 'read_excel', (), '', False, 'from pandas import read_excel\n'), ((47, 14, 47, 25), 'pandas.core.frame.DataFrame', 'DataFrame', ({}, {}), '()', False, 'from pandas.core.frame import DataFrame\n'), ((48, 14, 48, 25), 'pandas.core.frame.DataFrame', 'DataFrame', ({}, {}), '()', False, 'from pandas.core.frame import DataFrame\n'), ((49, 18, 49, 26), 'pandas.core.series.Series', 'Series', ({}, {}), '()', False, 'from pandas.core.series import Series\n'), ((50, 18, 50, 26), 'pandas.core.series.Series', 'Series', ({}, {}), '()', False, 'from pandas.core.series import Series\n'), ((64, 17, 64, 25), 'pandas.core.series.Series', 'Series', ({}, {}), '()', False, 'from pandas.core.series import Series\n'), ((67, 23, 67, 62), 'pandas.read_excel', 'read_excel', (), '', False, 'from pandas import read_excel\n'), ((150, 9, 150, 33), 'pytest.raises', 'pytest.raises', ({(150, 23, 150, 32): 'NameError'}, {}), '(NameError)', False, 'import pytest\n'), ((155, 9, 155, 33), 'pytest.raises', 'pytest.raises', ({(155, 23, 155, 32): 'TypeError'}, {}), '(TypeError)', False, 'import pytest\n'), ((159, 9, 159, 33), 'pytest.raises', 'pytest.raises', ({(159, 23, 159, 32): 'TypeError'}, {}), '(TypeError)', False, 'import pytest\n'), ((163, 9, 163, 36), 'pytest.raises', 'pytest.raises', ({(163, 23, 163, 35): 'RuntimeError'}, {}), '(RuntimeError)', False, 'import pytest\n'), ((170, 9, 170, 36), 'pytest.raises', 'pytest.raises', ({(170, 23, 170, 35): 'RuntimeError'}, {}), '(RuntimeError)', False, 'import pytest\n'), ((71, 25, 71, 81), 'datetime.datetime.strptime', 'datetime.datetime.strptime', ({(71, 52, 71, 63): 'date_string', (71, 65, 71, 80): '"""%Y%m%d-%H%M%S"""'}, {}), "(date_string, '%Y%m%d-%H%M%S')", False, 'import datetime\n'), ((77, 13, 77, 49), 'warnings.catch_warnings', 'warnings.catch_warnings', (), '', False, 'import warnings\n'), ((78, 12, 78, 43), 'warnings.simplefilter', 'warnings.simplefilter', ({(78, 34, 78, 42): '"""always"""'}, {}), "('always')", False, 'import warnings\n'), ((87, 13, 87, 49), 'warnings.catch_warnings', 'warnings.catch_warnings', (), '', False, 'import warnings\n'), ((88, 21, 88, 29), 'pandas.core.series.Series', 'Series', ({}, {}), '()', False, 'from pandas.core.series import Series\n'), ((97, 13, 97, 49), 'warnings.catch_warnings', 'warnings.catch_warnings', (), '', False, 'import warnings\n'), ((98, 12, 98, 43), 'warnings.simplefilter', 'warnings.simplefilter', ({(98, 34, 98, 42): '"""always"""'}, {}), "('always')", False, 'import warnings\n'), ((57, 30, 57, 100), 'pandas.read_excel', 'read_excel', (), '', False, 'from pandas import read_excel\n'), ((58, 16, 58, 75), 'pandas.util.testing.assert_series_equal', 'tm.assert_series_equal', (), '', True, 'import pandas.util.testing as tm\n'), ((72, 27, 72, 50), 'datetime.datetime.now', 'datetime.datetime.now', ({}, {}), '()', False, 'import datetime\n'), ((169, 45, 169, 53), 'pandas.core.series.Series', 'Series', ({}, {}), '()', False, 'from pandas.core.series import Series\n'), ((60, 30, 60, 87), 'pandas.read_excel', 'read_excel', (), '', False, 'from pandas import read_excel\n'), ((61, 16, 61, 74), 'pandas.util.testing.assert_frame_equal', 'tm.assert_frame_equal', (), '', True, 'import pandas.util.testing as tm\n'), ((79, 40, 79, 48), 'pandas.core.series.Series', 'Series', ({}, {}), '()', False, 'from pandas.core.series import Series\n'), ((100, 41, 100, 49), 'pandas.core.series.Series', 'Series', ({}, {}), '()', False, 'from pandas.core.series import Series\n'), ((114, 22, 114, 36), 'pathlib.Path', 'pathlib.Path', ({}, {}), '()', False, 'import pathlib\n'), ((122, 22, 122, 36), 'pathlib.Path', 'pathlib.Path', ({}, {}), '()', False, 'import pathlib\n')]