Skip to content

Commit 08a599b

Browse files
mroeschkejreback
authored andcommitted
CLN: Dead version checking code post minimum version bump (#27063)
* Remove dateutil version check tests * Remove more dead version checking code * Flake8 and fix bs4 comparison * Use import_optional_dependency again * Remove unused import * Change bs4 import test to check for ImportError and add whatsnew * Some linting * noqa necessary imports
1 parent ce86c21 commit 08a599b

File tree

13 files changed

+26
-106
lines changed

13 files changed

+26
-106
lines changed

doc/source/whatsnew/v0.25.0.rst

+1
Original file line numberDiff line numberDiff line change
@@ -538,6 +538,7 @@ Other API changes
538538
- Most Pandas classes had a ``__bytes__`` method, which was used for getting a python2-style bytestring representation of the object. This method has been removed as a part of dropping Python2 (:issue:`26447`)
539539
- The ``.str``-accessor has been disabled for 1-level :class:`MultiIndex`, use :meth:`MultiIndex.to_flat_index` if necessary (:issue:`23679`)
540540
- Removed support of gtk package for clipboards (:issue:`26563`)
541+
- Using an unsupported version of Beautiful Soup 4 will now raise an ``ImportError`` instead of a ``ValueError`` (:issue:`27063`)
541542

542543
.. _whatsnew_0250.deprecations:
543544

pandas/io/html.py

+2-5
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
"""
55

66
from collections import abc
7-
from distutils.version import LooseVersion
87
import numbers
98
import os
109
import re
@@ -830,10 +829,8 @@ def _parser_dispatch(flavor):
830829
if not _HAS_BS4:
831830
raise ImportError(
832831
"BeautifulSoup4 (bs4) not found, please install it")
833-
import bs4
834-
if LooseVersion(bs4.__version__) <= LooseVersion('4.2.0'):
835-
raise ValueError("A minimum version of BeautifulSoup 4.2.1 "
836-
"is required")
832+
# Although we call this above, we want to raise here right before use.
833+
bs4 = import_optional_dependency('bs4') # noqa:F841
837834

838835
else:
839836
if not _HAS_LXML:

pandas/io/pytables.py

-5
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55

66
import copy
77
from datetime import date, datetime
8-
from distutils.version import LooseVersion
98
import itertools
109
import os
1110
import re
@@ -227,10 +226,6 @@ def _tables():
227226
import tables
228227
_table_mod = tables
229228

230-
# version requirements
231-
if LooseVersion(tables.__version__) < LooseVersion('3.0.0'):
232-
raise ImportError("PyTables version >= 3.0.0 is required")
233-
234229
# set the file open policy
235230
# return the file open policy; this changes as of pytables 3.1
236231
# depending on the HDF5 version

pandas/tests/indexes/datetimes/test_timezones.py

+4-9
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
Tests for DatetimeIndex timezone-related methods
33
"""
44
from datetime import date, datetime, time, timedelta, tzinfo
5-
from distutils.version import LooseVersion
65

76
import dateutil
87
from dateutil.tz import gettz, tzlocal
@@ -554,14 +553,10 @@ def test_dti_construction_ambiguous_endpoint(self, tz):
554553
assert times[0] == Timestamp('2013-10-26 23:00', tz=tz, freq="H")
555554

556555
if str(tz).startswith('dateutil'):
557-
if LooseVersion(dateutil.__version__) < LooseVersion('2.6.0'):
558-
# see GH#14621
559-
assert times[-1] == Timestamp('2013-10-27 01:00:00+0000',
560-
tz=tz, freq="H")
561-
elif LooseVersion(dateutil.__version__) > LooseVersion('2.6.0'):
562-
# fixed ambiguous behavior
563-
assert times[-1] == Timestamp('2013-10-27 01:00:00+0100',
564-
tz=tz, freq="H")
556+
# fixed ambiguous behavior
557+
# see GH#14621
558+
assert times[-1] == Timestamp('2013-10-27 01:00:00+0100',
559+
tz=tz, freq="H")
565560
else:
566561
assert times[-1] == Timestamp('2013-10-27 01:00:00+0000',
567562
tz=tz, freq="H")

pandas/tests/indexes/datetimes/test_tools.py

-9
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,8 @@
22

33
import calendar
44
from datetime import datetime, time
5-
from distutils.version import LooseVersion
65
import locale
76

8-
import dateutil
97
from dateutil.parser import parse
108
from dateutil.tz.tz import tzoffset
119
import numpy as np
@@ -1739,8 +1737,6 @@ def test_parsers_dayfirst_yearfirst(self, cache):
17391737
# 2.5.2 20/12/21 [dayfirst=1, yearfirst=0] -> 2021-12-20 00:00:00
17401738
# 2.5.3 20/12/21 [dayfirst=1, yearfirst=0] -> 2021-12-20 00:00:00
17411739

1742-
is_lt_253 = LooseVersion(dateutil.__version__) < LooseVersion('2.5.3')
1743-
17441740
# str : dayfirst, yearfirst, expected
17451741
cases = {'10-11-12': [(False, False,
17461742
datetime(2012, 10, 11)),
@@ -1762,11 +1758,6 @@ def test_parsers_dayfirst_yearfirst(self, cache):
17621758
for date_str, values in cases.items():
17631759
for dayfirst, yearfirst, expected in values:
17641760

1765-
# odd comparisons across version
1766-
# let's just skip
1767-
if dayfirst and yearfirst and is_lt_253:
1768-
continue
1769-
17701761
# compare with dateutil result
17711762
dateutil_result = parse(date_str, dayfirst=dayfirst,
17721763
yearfirst=yearfirst)

pandas/tests/io/conftest.py

-7
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
from distutils.version import LooseVersion
21
import os
32

43
import pytest
@@ -43,12 +42,6 @@ def s3_resource(tips_file, jsonl_file):
4342
"""
4443
pytest.importorskip('s3fs')
4544
boto3 = pytest.importorskip('boto3')
46-
botocore = pytest.importorskip('botocore')
47-
48-
if LooseVersion(botocore.__version__) < LooseVersion("1.11.0"):
49-
# botocore leaks an uncatchable ResourceWarning before 1.11.0;
50-
# see GH 23731 and https://github.com/boto/botocore/issues/1464
51-
pytest.skip("botocore is leaking resources before 1.11.0")
5245

5346
with tm.ensure_safe_environment_variables():
5447
# temporary workaround as moto fails for botocore >= 1.11 otherwise,

pandas/tests/io/excel/test_style.py

+2-11
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
from distutils.version import LooseVersion
2-
31
import numpy as np
42
import pytest
53

@@ -107,15 +105,8 @@ def custom_converter(css):
107105
assert cell1.font.color.rgb != cell2.font.color.rgb
108106
assert cell2.font.color.rgb == alpha + '0000FF'
109107
elif ref == 'D4':
110-
# This fails with engine=xlsxwriter due to
111-
# https://bitbucket.org/openpyxl/openpyxl/issues/800
112-
if engine == 'xlsxwriter' \
113-
and (LooseVersion(openpyxl.__version__) <
114-
LooseVersion('2.4.6')):
115-
pass
116-
else:
117-
assert cell1.font.underline != cell2.font.underline
118-
assert cell2.font.underline == 'single'
108+
assert cell1.font.underline != cell2.font.underline
109+
assert cell2.font.underline == 'single'
119110
elif ref == 'B5':
120111
assert not cell1.border.left.style
121112
assert (cell2.border.top.style ==

pandas/tests/io/pytables/test_pytables.py

+1-2
Original file line numberDiff line numberDiff line change
@@ -43,8 +43,7 @@
4343
'release beyong 3.4.4 to support numpy 1.16x'))
4444

4545

46-
_default_compressor = ('blosc' if LooseVersion(tables.__version__) >=
47-
LooseVersion('2.2') else 'zlib')
46+
_default_compressor = 'blosc'
4847

4948

5049
ignore_natural_naming_warning = pytest.mark.filterwarnings(

pandas/tests/io/test_html.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ def assert_framelist_equal(list1, list2, *args, **kwargs):
5454
def test_bs4_version_fails(monkeypatch, datapath):
5555
import bs4
5656
monkeypatch.setattr(bs4, '__version__', '4.2')
57-
with pytest.raises(ValueError, match="minimum version"):
57+
with pytest.raises(ImportError, match="Pandas requires version"):
5858
read_html(datapath("io", "data", "spam.html"), flavor='bs4')
5959

6060

pandas/tests/io/test_parquet.py

+4-9
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
""" test parquet compat """
22
import datetime
3-
from distutils.version import LooseVersion
43
import os
54
from warnings import catch_warnings
65

@@ -454,10 +453,8 @@ class TestParquetFastParquet(Base):
454453
def test_basic(self, fp, df_full):
455454
df = df_full
456455

457-
# additional supported types for fastparquet
458-
if LooseVersion(fastparquet.__version__) >= LooseVersion('0.1.4'):
459-
df['datetime_tz'] = pd.date_range('20130101', periods=3,
460-
tz='US/Eastern')
456+
df['datetime_tz'] = pd.date_range('20130101', periods=3,
457+
tz='US/Eastern')
461458
df['timedelta'] = pd.timedelta_range('1 day', periods=3)
462459
check_round_trip(df, fp)
463460

@@ -485,8 +482,6 @@ def test_unsupported(self, fp):
485482
self.check_error_on_write(df, fp, ValueError)
486483

487484
def test_categorical(self, fp):
488-
if LooseVersion(fastparquet.__version__) < LooseVersion("0.1.3"):
489-
pytest.skip("CategoricalDtype not supported for older fp")
490485
df = pd.DataFrame({'a': pd.Categorical(list('abc'))})
491486
check_round_trip(df, fp)
492487

@@ -512,7 +507,7 @@ def test_partition_cols_supported(self, fp, df_full):
512507
df.to_parquet(path, engine="fastparquet",
513508
partition_cols=partition_cols, compression=None)
514509
assert os.path.exists(path)
515-
import fastparquet
510+
import fastparquet # noqa: F811
516511
actual_partition_cols = fastparquet.ParquetFile(path, False).cats
517512
assert len(actual_partition_cols) == 2
518513

@@ -524,7 +519,7 @@ def test_partition_on_supported(self, fp, df_full):
524519
df.to_parquet(path, engine="fastparquet", compression=None,
525520
partition_on=partition_cols)
526521
assert os.path.exists(path)
527-
import fastparquet
522+
import fastparquet # noqa: F811
528523
actual_partition_cols = fastparquet.ParquetFile(path, False).cats
529524
assert len(actual_partition_cols) == 2
530525

pandas/tests/scalar/timestamp/test_rendering.py

+2-9
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
1-
from distutils.version import LooseVersion
21
import pprint
32

4-
import dateutil
53
import pytest
64
import pytz # noqa # a test below uses pytz but only inside a `eval` call
75

@@ -10,13 +8,8 @@
108

119
class TestTimestampRendering:
1210

13-
# dateutil zone change (only matters for repr)
14-
if LooseVersion(dateutil.__version__) >= LooseVersion('2.6.0'):
15-
timezones = ['UTC', 'Asia/Tokyo', 'US/Eastern',
16-
'dateutil/US/Pacific']
17-
else:
18-
timezones = ['UTC', 'Asia/Tokyo', 'US/Eastern',
19-
'dateutil/America/Los_Angeles']
11+
timezones = ['UTC', 'Asia/Tokyo', 'US/Eastern',
12+
'dateutil/US/Pacific']
2013

2114
@pytest.mark.parametrize('tz', timezones)
2215
@pytest.mark.parametrize('freq', ['D', 'M', 'S', 'N'])

pandas/tests/scalar/timestamp/test_timezones.py

+9-19
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
Tests for Timestamp timezone-related methods
33
"""
44
from datetime import date, datetime, timedelta
5-
from distutils.version import LooseVersion
65

76
import dateutil
87
from dateutil.tz import gettz, tzoffset
@@ -145,31 +144,22 @@ def test_tz_localize_ambiguous_compat(self):
145144
assert result_pytz.value == result_dateutil.value
146145
assert result_pytz.value == 1382835600000000000
147146

148-
if LooseVersion(dateutil.__version__) < LooseVersion('2.6.0'):
149-
# dateutil 2.6 buggy w.r.t. ambiguous=0
150-
# see gh-14621
151-
# see https://github.com/dateutil/dateutil/issues/321
152-
assert (result_pytz.to_pydatetime().tzname() ==
153-
result_dateutil.to_pydatetime().tzname())
154-
assert str(result_pytz) == str(result_dateutil)
155-
elif LooseVersion(dateutil.__version__) > LooseVersion('2.6.0'):
156-
# fixed ambiguous behavior
157-
assert result_pytz.to_pydatetime().tzname() == 'GMT'
158-
assert result_dateutil.to_pydatetime().tzname() == 'BST'
159-
assert str(result_pytz) != str(result_dateutil)
147+
# fixed ambiguous behavior
148+
# see gh-14621
149+
assert result_pytz.to_pydatetime().tzname() == 'GMT'
150+
assert result_dateutil.to_pydatetime().tzname() == 'BST'
151+
assert str(result_pytz) != str(result_dateutil)
160152

161153
# 1 hour difference
162154
result_pytz = naive.tz_localize(pytz_zone, ambiguous=1)
163155
result_dateutil = naive.tz_localize(dateutil_zone, ambiguous=1)
164156
assert result_pytz.value == result_dateutil.value
165157
assert result_pytz.value == 1382832000000000000
166158

167-
# dateutil < 2.6 is buggy w.r.t. ambiguous timezones
168-
if LooseVersion(dateutil.__version__) > LooseVersion('2.5.3'):
169-
# see gh-14621
170-
assert str(result_pytz) == str(result_dateutil)
171-
assert (result_pytz.to_pydatetime().tzname() ==
172-
result_dateutil.to_pydatetime().tzname())
159+
# see gh-14621
160+
assert str(result_pytz) == str(result_dateutil)
161+
assert (result_pytz.to_pydatetime().tzname() ==
162+
result_dateutil.to_pydatetime().tzname())
173163

174164
@pytest.mark.parametrize('tz', [pytz.timezone('US/Eastern'),
175165
gettz('US/Eastern'),

pandas/tests/tseries/offsets/test_offsets.py

-20
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
from datetime import date, datetime, timedelta
2-
from distutils.version import LooseVersion
32

43
import numpy as np
54
import pytest
@@ -2998,25 +2997,6 @@ def _make_timestamp(self, string, hrs_offset, tz):
29982997
offset_string = '-{hrs:02d}00'.format(hrs=-1 * hrs_offset)
29992998
return Timestamp(string + offset_string).tz_convert(tz)
30002999

3001-
def test_fallback_plural(self):
3002-
# test moving from daylight savings to standard time
3003-
import dateutil
3004-
for tz, utc_offsets in self.timezone_utc_offsets.items():
3005-
hrs_pre = utc_offsets['utc_offset_daylight']
3006-
hrs_post = utc_offsets['utc_offset_standard']
3007-
3008-
if LooseVersion(dateutil.__version__) < LooseVersion('2.6.0'):
3009-
# buggy ambiguous behavior in 2.6.0
3010-
# GH 14621
3011-
# https://github.com/dateutil/dateutil/issues/321
3012-
self._test_all_offsets(
3013-
n=3, tstart=self._make_timestamp(self.ts_pre_fallback,
3014-
hrs_pre, tz),
3015-
expected_utc_offset=hrs_post)
3016-
elif LooseVersion(dateutil.__version__) > LooseVersion('2.6.0'):
3017-
# fixed, but skip the test
3018-
continue
3019-
30203000
def test_springforward_plural(self):
30213001
# test moving from standard to daylight savings
30223002
for tz, utc_offsets in self.timezone_utc_offsets.items():

0 commit comments

Comments
 (0)