diff --git a/AUTHORS.rst b/AUTHORS.rst index f0e6c22725c46dfa9709134f3eaf36a9247fffbc..e04ff2ffa0bb7743a0d6c5f47fe60b9773921cfc 100644 --- a/AUTHORS.rst +++ b/AUTHORS.rst @@ -41,6 +41,7 @@ Thanks to all those who participate in the project (in alphabetical order): * Greg Lehmann * Heikki Junes * Israel Barth Rubio +* Jacob Middag * James Smagala * JarekPS * Jean Pierre Huart diff --git a/conftest.py b/conftest.py index 1a1e7f0401655b149bb26d618a6dfce2c516726f..56c96365f8a55794fadb74bbc9a628359b5afbad 100644 --- a/conftest.py +++ b/conftest.py @@ -38,8 +38,9 @@ def pytest_runtest_setup(item): if not NUMPY: pytest.skip("Numpy must be installed") elif item.get_closest_marker("pandas_required"): - from openpyxl import PANDAS - if not PANDAS: + try: + import pandas + except ImportError as e: pytest.skip("Pandas must be installed") elif item.get_closest_marker("no_pypy"): if platform.python_implementation() == "PyPy": diff --git a/openpyxl/__init__.py b/openpyxl/__init__.py index f38c545ed90cf16a889e8eb89f57410da4d23435..111828b16f76c93f399b681fffe93948404068a6 100644 --- a/openpyxl/__init__.py +++ b/openpyxl/__init__.py @@ -1,7 +1,7 @@ # Copyright (c) 2010-2020 openpyxl -from openpyxl.compat.numbers import NUMPY, PANDAS +from openpyxl.compat.numbers import NUMPY from openpyxl.xml import DEFUSEDXML, LXML from openpyxl.workbook import Workbook from openpyxl.reader.excel import load_workbook as open diff --git a/openpyxl/cell/cell.py b/openpyxl/cell/cell.py index 61687cb94363bba58f0d0f2ed2ec773466da80de..022d6248c74330e2d63dda8c749b144888a101ff 100644 --- a/openpyxl/cell/cell.py +++ b/openpyxl/cell/cell.py @@ -37,12 +37,6 @@ TIME_FORMATS = { datetime.time:numbers.FORMAT_DATE_TIME6, datetime.timedelta:numbers.FORMAT_DATE_TIMEDELTA, } -try: - from pandas import Timestamp - TIME_TYPES = TIME_TYPES + (Timestamp,) - TIME_FORMATS[Timestamp] = numbers.FORMAT_DATE_DATETIME -except ImportError: - pass STRING_TYPES = (str, bytes) KNOWN_TYPES = NUMERIC_TYPES + TIME_TYPES + STRING_TYPES + (bool, type(None)) @@ -83,6 +77,17 @@ def get_type(t, value): return dt +def get_time_format(t): + value = TIME_FORMATS.get(t) + if value: + return value + for base in t.mro()[1:]: + value = TIME_FORMATS.get(base) + if value: + TIME_FORMATS[t] = value + return value + + class Cell(StyleableObject): """Describes cell associated properties. @@ -185,8 +190,9 @@ class Cell(StyleableObject): elif dt == 'd': if not is_date_format(self.number_format): - self.number_format = TIME_FORMATS[t] - self.data_type = "d" + self.number_format = get_time_format(t) + if self.number_format is None: + raise ValueError("Could not get time format for {0!r}".format(value)) elif dt == "s": value = self.check_string(value) diff --git a/openpyxl/cell/tests/test_cell.py b/openpyxl/cell/tests/test_cell.py index 30b404b9af2874c6c11deb6f36e0db2cf4263257..48c996cabc0b635441ff38c5c4bdea9402c721ab 100644 --- a/openpyxl/cell/tests/test_cell.py +++ b/openpyxl/cell/tests/test_cell.py @@ -15,7 +15,7 @@ import pytest # package imports from openpyxl.comments import Comment -from openpyxl.cell.cell import ERROR_CODES +from openpyxl.cell.cell import ERROR_CODES, get_time_format @pytest.fixture @@ -146,6 +146,23 @@ def test_timstamp(dummy_cell): cell.value = Timestamp("2018-09-05") assert cell.number_format == "yyyy-mm-dd h:mm:ss" +def test_time_format_datetime_subclass(): + class TestDatetime(datetime): + pass + + number_format = get_time_format(TestDatetime) + assert number_format == "yyyy-mm-dd h:mm:ss" + +def test_time_format_date_subclass(): + class TestDate(date): + pass + + number_format = get_time_format(TestDate) + assert number_format == "yyyy-mm-dd" + +def test_time_format_no_date_subclass(): + number_format = get_time_format(object) + assert number_format == None def test_not_overwrite_time_format(dummy_cell): cell = dummy_cell diff --git a/openpyxl/compat/numbers.py b/openpyxl/compat/numbers.py index e41dead516b42d761484f5376ca0b92c04118e5b..c76bccb8b67e94bdc82a0976fca7e30a18e94a05 100644 --- a/openpyxl/compat/numbers.py +++ b/openpyxl/compat/numbers.py @@ -42,10 +42,3 @@ if NUMPY: numpy.bool_, numpy.floating, numpy.integer) - - -try: - import pandas - PANDAS = True -except ImportError: - PANDAS = False