Skip to content

Commit e2fd405

Browse files
committed
Merge pull request #7285 from cpcloud/openpyxl-format-string-fix-7284
BUG/CI/TST: fix format strings
2 parents b0c8110 + c9b5783 commit e2fd405

File tree

6 files changed

+55
-32
lines changed

6 files changed

+55
-32
lines changed

ci/requirements-2.6.txt

+1-1
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,6 @@ sqlalchemy==0.8.1
1010
scipy==0.11.0
1111
statsmodels==0.4.3
1212
xlwt==0.7.5
13-
openpyxl==1.6.2
13+
openpyxl==2.0.3
1414
xlsxwriter==0.4.6
1515
xlrd==0.9.2

ci/requirements-3.2.txt

-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
python-dateutil==2.1
22
pytz==2013b
3-
openpyxl==1.6.2
43
xlsxwriter==0.4.6
54
xlrd==0.9.2
65
numpy==1.7.1

doc/source/v0.14.1.txt

+2
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@ users upgrade to this version.
2727

2828
API changes
2929
~~~~~~~~~~~
30+
- Openpyxl now raises a ValueError on construction of the openpyxl writer
31+
instead of warning on pandas import (:issue:`7284`).
3032

3133
.. _whatsnew_0141.prior_deprecations:
3234

pandas/compat/openpyxl_compat.py

+10-12
Original file line numberDiff line numberDiff line change
@@ -9,18 +9,16 @@
99
start_ver = '1.6.1'
1010
stop_ver = '2.0.0'
1111

12+
1213
def is_compat():
13-
"""
14-
Detect whether the installed version of openpyxl is supported
15-
Returns True/False if openpyxl is installed, None otherwise
16-
"""
17-
try:
18-
import openpyxl
19-
except ImportError:
20-
return None
14+
"""Detect whether the installed version of openpyxl is supported.
2115
16+
Returns
17+
-------
18+
compat : bool
19+
``True`` if openpyxl is installed and is between versions 1.6.1 and
20+
2.0.0, ``False`` otherwise.
21+
"""
22+
import openpyxl
2223
ver = LooseVersion(openpyxl.__version__)
23-
if ver < LooseVersion(start_ver) or LooseVersion(stop_ver) <= ver:
24-
return False
25-
26-
return True
24+
return LooseVersion(start_ver) < ver <= LooseVersion(stop_ver)

pandas/io/excel.py

+6-6
Original file line numberDiff line numberDiff line change
@@ -523,6 +523,11 @@ class _OpenpyxlWriter(ExcelWriter):
523523
supported_extensions = ('.xlsx', '.xlsm')
524524

525525
def __init__(self, path, engine=None, **engine_kwargs):
526+
if not openpyxl_compat.is_compat():
527+
raise ValueError('Installed openpyxl is not supported at this '
528+
'time. Use >={0} and '
529+
'<{1}.'.format(openpyxl_compat.start_ver,
530+
openpyxl_compat.stop_ver))
526531
# Use the openpyxl module as the Excel writer.
527532
from openpyxl.workbook import Workbook
528533

@@ -618,12 +623,7 @@ def _convert_to_style(cls, style_dict):
618623

619624
return xls_style
620625

621-
622-
if openpyxl_compat.is_compat():
623-
register_writer(_OpenpyxlWriter)
624-
else:
625-
warn('Installed openpyxl is not supported at this time. Use >={} and <{}.'
626-
.format(openpyxl_compat.start_ver, openpyxl_compat.stop_ver))
626+
register_writer(_OpenpyxlWriter)
627627

628628

629629
class _XlwtWriter(ExcelWriter):

pandas/io/tests/test_excel.py

+36-12
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55
import os
66
from distutils.version import LooseVersion
77

8+
import operator
9+
import functools
810
import nose
911

1012
from numpy import nan
@@ -45,10 +47,6 @@ def _skip_if_no_openpyxl():
4547
except ImportError:
4648
raise nose.SkipTest('openpyxl not installed, skipping')
4749

48-
if not openpyxl_compat.is_compat():
49-
raise nose.SkipTest('need %s <= openpyxl < %s, skipping' %
50-
(openpyxl_compat.start_ver, openpyxl_compat.stop_ver))
51-
5250

5351
def _skip_if_no_xlsxwriter():
5452
try:
@@ -884,7 +882,6 @@ def test_to_excel_output_encoding(self):
884882
result = read_excel(filename, 'TestSheet', encoding='utf8')
885883
tm.assert_frame_equal(result, df)
886884

887-
888885
def test_to_excel_unicode_filename(self):
889886
_skip_if_no_xlrd()
890887
with ensure_clean(u('\u0192u.') + self.ext) as filename:
@@ -1094,13 +1091,36 @@ def test_swapped_columns(self):
10941091
tm.assert_series_equal(write_frame['B'], read_frame['B'])
10951092

10961093

1094+
def raise_wrapper(orig_method):
1095+
@functools.wraps(orig_method)
1096+
def wrapped(self, *args, **kwargs):
1097+
_skip_if_no_openpyxl()
1098+
if openpyxl_compat.is_compat():
1099+
orig_method(self, *args, **kwargs)
1100+
else:
1101+
msg = 'Installed openpyxl is not supported at this time\. Use.+'
1102+
with tm.assertRaisesRegexp(ValueError, msg):
1103+
orig_method(self, *args, **kwargs)
1104+
return wrapped
1105+
1106+
1107+
def raise_on_incompat_version(cls):
1108+
methods = filter(operator.methodcaller('startswith', 'test_'), dir(cls))
1109+
for method in methods:
1110+
setattr(cls, method, raise_wrapper(getattr(cls, method)))
1111+
return cls
1112+
1113+
1114+
@raise_on_incompat_version
10971115
class OpenpyxlTests(ExcelWriterBase, tm.TestCase):
10981116
ext = '.xlsx'
10991117
engine_name = 'openpyxl'
1100-
check_skip = staticmethod(_skip_if_no_openpyxl)
1118+
check_skip = staticmethod(lambda *args, **kwargs: None)
11011119

11021120
def test_to_excel_styleconverter(self):
11031121
_skip_if_no_openpyxl()
1122+
if not openpyxl_compat.is_compat():
1123+
raise nose.SkipTest('incompatiable openpyxl version')
11041124

11051125
import openpyxl
11061126

@@ -1114,17 +1134,17 @@ def test_to_excel_styleconverter(self):
11141134
xlsx_style = _OpenpyxlWriter._convert_to_style(hstyle)
11151135
self.assertTrue(xlsx_style.font.bold)
11161136
self.assertEqual(openpyxl.style.Border.BORDER_THIN,
1117-
xlsx_style.borders.top.border_style)
1137+
xlsx_style.borders.top.border_style)
11181138
self.assertEqual(openpyxl.style.Border.BORDER_THIN,
1119-
xlsx_style.borders.right.border_style)
1139+
xlsx_style.borders.right.border_style)
11201140
self.assertEqual(openpyxl.style.Border.BORDER_THIN,
1121-
xlsx_style.borders.bottom.border_style)
1141+
xlsx_style.borders.bottom.border_style)
11221142
self.assertEqual(openpyxl.style.Border.BORDER_THIN,
1123-
xlsx_style.borders.left.border_style)
1143+
xlsx_style.borders.left.border_style)
11241144
self.assertEqual(openpyxl.style.Alignment.HORIZONTAL_CENTER,
1125-
xlsx_style.alignment.horizontal)
1145+
xlsx_style.alignment.horizontal)
11261146
self.assertEqual(openpyxl.style.Alignment.VERTICAL_TOP,
1127-
xlsx_style.alignment.vertical)
1147+
xlsx_style.alignment.vertical)
11281148

11291149

11301150
class XlwtTests(ExcelWriterBase, tm.TestCase):
@@ -1160,6 +1180,7 @@ class XlsxWriterTests(ExcelWriterBase, tm.TestCase):
11601180
check_skip = staticmethod(_skip_if_no_xlsxwriter)
11611181

11621182

1183+
@raise_on_incompat_version
11631184
class OpenpyxlTests_NoMerge(ExcelWriterBase, tm.TestCase):
11641185
ext = '.xlsx'
11651186
engine_name = 'openpyxl'
@@ -1196,6 +1217,8 @@ def test_ExcelWriter_dispatch(self):
11961217
import xlsxwriter
11971218
writer_klass = _XlsxWriter
11981219
except ImportError:
1220+
if not openpyxl_compat.is_compat():
1221+
raise nose.SkipTest('incompatible openpyxl version')
11991222
_skip_if_no_openpyxl()
12001223
writer_klass = _OpenpyxlWriter
12011224

@@ -1246,6 +1269,7 @@ def check_called(func):
12461269
check_called(lambda: df.to_excel('something.xls', engine='dummy'))
12471270
set_option('io.excel.xlsx.writer', val)
12481271

1272+
12491273
if __name__ == '__main__':
12501274
nose.runmodule(argv=[__file__, '-vvs', '-x', '--pdb', '--pdb-failure'],
12511275
exit=False)

0 commit comments

Comments
 (0)