diff --git a/pandas/_libs/tslibs/timestamps.pyx b/pandas/_libs/tslibs/timestamps.pyx index 317dc769636fb..03ed26337d539 100644 --- a/pandas/_libs/tslibs/timestamps.pyx +++ b/pandas/_libs/tslibs/timestamps.pyx @@ -36,7 +36,6 @@ from pandas._libs.tslibs.tzconversion import ( # Constants _zero_time = datetime_time(0, 0) _no_input = object() -PY36 = sys.version_info >= (3, 6) # ---------------------------------------------------------------------- @@ -982,9 +981,8 @@ default 'raise' else: kwargs = {'year': dts.year, 'month': dts.month, 'day': dts.day, 'hour': dts.hour, 'minute': dts.min, 'second': dts.sec, - 'microsecond': dts.us, 'tzinfo': _tzinfo} - if PY36: - kwargs['fold'] = fold + 'microsecond': dts.us, 'tzinfo': _tzinfo, + 'fold': fold} ts_input = datetime(**kwargs) ts = convert_datetime_to_tsobject(ts_input, _tzinfo) diff --git a/pandas/compat/__init__.py b/pandas/compat/__init__.py index 890d0aca0019d..684fbbc23c86c 100644 --- a/pandas/compat/__init__.py +++ b/pandas/compat/__init__.py @@ -12,7 +12,6 @@ import sys import warnings -PY36 = sys.version_info >= (3, 6) PY37 = sys.version_info >= (3, 7) PY38 = sys.version_info >= (3, 8) PYPY = platform.python_implementation() == "PyPy" diff --git a/pandas/core/common.py b/pandas/core/common.py index 565f5076fdddb..133e60de5d694 100644 --- a/pandas/core/common.py +++ b/pandas/core/common.py @@ -5,7 +5,7 @@ """ import collections -from collections import OrderedDict, abc +from collections import abc from datetime import datetime, timedelta from functools import partial import inspect @@ -14,7 +14,6 @@ import numpy as np from pandas._libs import lib, tslibs -from pandas.compat import PY36 from pandas.core.dtypes.cast import construct_1d_object_array_from_listlike from pandas.core.dtypes.common import ( @@ -215,16 +214,6 @@ def try_sort(iterable): return listed -def dict_keys_to_ordered_list(mapping): - # when pandas drops support for Python < 3.6, this function - # can be replaced by a simple list(mapping.keys()) - if PY36 or isinstance(mapping, OrderedDict): - keys = list(mapping.keys()) - else: - keys = try_sort(mapping) - return keys - - def asarray_tuplesafe(values, dtype=None): if not (isinstance(values, (list, tuple)) or hasattr(values, "__array__")): diff --git a/pandas/core/dtypes/common.py b/pandas/core/dtypes/common.py index 1ed54c12f4a34..635bc5ce03680 100644 --- a/pandas/core/dtypes/common.py +++ b/pandas/core/dtypes/common.py @@ -6,7 +6,6 @@ from pandas._libs import algos, lib from pandas._libs.tslibs import conversion -from pandas.compat import PY36 from pandas.core.dtypes.dtypes import ( CategoricalDtype, @@ -1266,9 +1265,6 @@ def _is_unorderable_exception(e: TypeError) -> bool: """ Check if the exception raised is an unorderable exception. - The error message differs for 3 <= PY <= 3.5 and PY >= 3.6, so - we need to condition based on Python version. - Parameters ---------- e : Exception or sub-class @@ -1276,14 +1272,10 @@ def _is_unorderable_exception(e: TypeError) -> bool: Returns ------- - boolean + bool Whether or not the exception raised is an unorderable exception. """ - - if PY36: - return "'>' not supported between instances of" in str(e) - - return "unorderable" in str(e) + return "'>' not supported between instances of" in str(e) def needs_i8_conversion(arr_or_dtype) -> bool: diff --git a/pandas/core/frame.py b/pandas/core/frame.py index ebee8b10896be..231f3bf56fc36 100644 --- a/pandas/core/frame.py +++ b/pandas/core/frame.py @@ -34,7 +34,6 @@ from pandas._config import get_option from pandas._libs import algos as libalgos, lib -from pandas.compat import PY36 from pandas.compat.numpy import function as nv from pandas.util._decorators import ( Appender, @@ -3498,16 +3497,12 @@ def assign(self, **kwargs): Notes ----- Assigning multiple columns within the same ``assign`` is possible. - For Python 3.6 and above, later items in '\*\*kwargs' may refer to - newly created or modified columns in 'df'; items are computed and - assigned into 'df' in order. For Python 3.5 and below, the order of - keyword arguments is not specified, you cannot refer to newly created - or modified columns. All items are computed first, and then assigned - in alphabetical order. + Later items in '\*\*kwargs' may refer to newly created or modified + columns in 'df'; items are computed and assigned into 'df' in order. .. versionchanged:: 0.23.0 - Keyword argument order is maintained for Python 3.6 and later. + Keyword argument order is maintained. Examples -------- @@ -3533,9 +3528,8 @@ def assign(self, **kwargs): Portland 17.0 62.6 Berkeley 25.0 77.0 - In Python 3.6+, you can create multiple columns within the same assign - where one of the columns depends on another one defined within the same - assign: + You can create multiple columns within the same assign where one + of the columns depends on another one defined within the same assign: >>> df.assign(temp_f=lambda x: x['temp_c'] * 9 / 5 + 32, ... temp_k=lambda x: (x['temp_f'] + 459.67) * 5 / 9) @@ -3545,21 +3539,8 @@ def assign(self, **kwargs): """ data = self.copy() - # >= 3.6 preserve order of kwargs - if PY36: - for k, v in kwargs.items(): - data[k] = com.apply_if_callable(v, data) - else: - # <= 3.5: do all calculations first... - results = OrderedDict() - for k, v in kwargs.items(): - results[k] = com.apply_if_callable(v, data) - - # <= 3.5 and earlier - results = sorted(results.items()) - # ... and then assign - for k, v in results: - data[k] = v + for k, v in kwargs.items(): + data[k] = com.apply_if_callable(v, data) return data def _sanitize_column(self, key, value, broadcast=True): diff --git a/pandas/core/generic.py b/pandas/core/generic.py index 1b892c02ba7bf..47a0582edbea4 100644 --- a/pandas/core/generic.py +++ b/pandas/core/generic.py @@ -8,7 +8,6 @@ import re from textwrap import dedent from typing import ( - TYPE_CHECKING, Any, Callable, Dict, @@ -190,12 +189,7 @@ class NDFrame(PandasObject, SelectionMixin): _metadata = [] # type: List[str] _is_copy = None _data = None # type: BlockManager - - if TYPE_CHECKING: - # TODO(PY36): replace with _attrs : Dict[Hashable, Any] - # We need the TYPE_CHECKING, because _attrs is not a class attribute - # and Py35 doesn't support the new syntax. - _attrs = {} # type: Dict[Optional[Hashable], Any] + _attrs: Dict[Optional[Hashable], Any] # ---------------------------------------------------------------------- # Constructors diff --git a/pandas/core/groupby/generic.py b/pandas/core/groupby/generic.py index dda98d2dd438b..8f0b8a1e37af2 100644 --- a/pandas/core/groupby/generic.py +++ b/pandas/core/groupby/generic.py @@ -28,7 +28,6 @@ import numpy as np from pandas._libs import Timestamp, lib -from pandas.compat import PY36 from pandas.util._decorators import Appender, Substitution from pandas.core.dtypes.cast import ( @@ -233,10 +232,6 @@ def aggregate(self, func=None, *args, **kwargs): no_arg_message = "Must provide 'func' or named aggregation **kwargs." if relabeling: columns = list(kwargs) - if not PY36: - # sort for 3.5 and earlier - columns = list(sorted(columns)) - func = [kwargs[col] for col in columns] kwargs = {} if not columns: @@ -1804,9 +1799,6 @@ def _normalize_keyword_aggregation(kwargs): >>> _normalize_keyword_aggregation({'output': ('input', 'sum')}) (OrderedDict([('input', ['sum'])]), ('output',), [('input', 'sum')]) """ - if not PY36: - kwargs = OrderedDict(sorted(kwargs.items())) - # Normalize the aggregation functions as Dict[column, List[func]], # process normally, then fixup the names. # TODO(Py35): When we drop python 3.5, change this to diff --git a/pandas/core/internals/construction.py b/pandas/core/internals/construction.py index 05a2803b3fc2f..e4a6ca85ac05c 100644 --- a/pandas/core/internals/construction.py +++ b/pandas/core/internals/construction.py @@ -2,14 +2,12 @@ Functions for preparing various inputs passed to the DataFrame or Series constructors before passing them to a BlockManager. """ -from collections import OrderedDict, abc +from collections import abc import numpy as np import numpy.ma as ma from pandas._libs import lib -import pandas.compat as compat -from pandas.compat import PY36 from pandas.core.dtypes.cast import ( construct_1d_arraylike_from_scalar, @@ -235,7 +233,7 @@ def init_dict(data, index, columns, dtype=None): arrays.loc[missing] = [val] * missing.sum() else: - keys = com.dict_keys_to_ordered_list(data) + keys = list(data.keys()) columns = data_names = Index(keys) arrays = (com.maybe_iterable_to_list(data[k]) for k in keys) # GH#24096 need copy to be deep for datetime64tz case @@ -331,7 +329,6 @@ def extract_index(data): have_raw_arrays = False have_series = False have_dicts = False - have_ordered = False for val in data: if isinstance(val, ABCSeries): @@ -339,8 +336,6 @@ def extract_index(data): indexes.append(val.index) elif isinstance(val, dict): have_dicts = True - if isinstance(val, OrderedDict): - have_ordered = True indexes.append(list(val.keys())) elif is_list_like(val) and getattr(val, "ndim", 1) == 1: have_raw_arrays = True @@ -352,7 +347,7 @@ def extract_index(data): if have_series: index = _union_indexes(indexes) elif have_dicts: - index = _union_indexes(indexes, sort=not (compat.PY36 or have_ordered)) + index = _union_indexes(indexes, sort=False) if have_raw_arrays: lengths = list(set(raw_lengths)) @@ -531,7 +526,7 @@ def _list_of_dict_to_arrays(data, columns, coerce_float=False, dtype=None): """Convert list of dicts to numpy arrays if `columns` is not passed, column names are inferred from the records - - for OrderedDict and (on Python>=3.6) dicts, the column names match + - for OrderedDict and dicts, the column names match the key insertion-order from the first record to the last. - For other kinds of dict-likes, the keys are lexically sorted. @@ -550,8 +545,7 @@ def _list_of_dict_to_arrays(data, columns, coerce_float=False, dtype=None): """ if columns is None: gen = (list(x.keys()) for x in data) - types = (dict, OrderedDict) if PY36 else OrderedDict - sort = not any(isinstance(d, types) for d in data) + sort = not any(isinstance(d, dict) for d in data) columns = lib.fast_unique_multiple_list_gen(gen, sort=sort) # assure that they are of the base dict class and not of derived diff --git a/pandas/core/reshape/concat.py b/pandas/core/reshape/concat.py index 772ac1cd93059..3c1b2b1eb11d2 100644 --- a/pandas/core/reshape/concat.py +++ b/pandas/core/reshape/concat.py @@ -293,7 +293,7 @@ def __init__( if isinstance(objs, dict): if keys is None: - keys = com.dict_keys_to_ordered_list(objs) + keys = list(objs.keys()) objs = [objs[k] for k in keys] else: objs = list(objs) diff --git a/pandas/core/series.py b/pandas/core/series.py index 7327c2d543836..c5e639fef8c5b 100644 --- a/pandas/core/series.py +++ b/pandas/core/series.py @@ -1,7 +1,6 @@ """ Data structure for 1-dimensional cross-sectional and time series data """ -from collections import OrderedDict from io import StringIO from shutil import get_terminal_size from textwrap import dedent @@ -13,7 +12,6 @@ from pandas._config import get_option from pandas._libs import index as libindex, lib, reshape, tslibs -from pandas.compat import PY36 from pandas.compat.numpy import function as nv from pandas.util._decorators import Appender, Substitution, deprecate from pandas.util._validators import validate_bool_kwarg, validate_percentile @@ -364,13 +362,6 @@ def _init_dict(self, data, index=None, dtype=None): # Now we just make sure the order is respected, if any if data and index is not None: s = s.reindex(index, copy=False) - elif not PY36 and not isinstance(data, OrderedDict) and data: - # Need the `and data` to avoid sorting Series(None, index=[...]) - # since that isn't really dict-like - try: - s = s.sort_index() - except TypeError: - pass return s._data, s.index @classmethod diff --git a/pandas/io/pickle.py b/pandas/io/pickle.py index 5e066c4f9ecbd..0a0ccedd78f00 100644 --- a/pandas/io/pickle.py +++ b/pandas/io/pickle.py @@ -2,7 +2,7 @@ import pickle import warnings -from pandas.compat import PY36, pickle_compat as pc +from pandas.compat import pickle_compat as pc from pandas.io.common import _get_handle, _stringify_path @@ -140,9 +140,7 @@ def read_pickle(path, compression="infer"): # 1) try standard library Pickle # 2) try pickle_compat (older pandas version) to handle subclass changes - excs_to_catch = (AttributeError, ImportError) - if PY36: - excs_to_catch += (ModuleNotFoundError,) + excs_to_catch = (AttributeError, ImportError, ModuleNotFoundError) try: with warnings.catch_warnings(record=True): diff --git a/pandas/tests/extension/json/test_json.py b/pandas/tests/extension/json/test_json.py index bc75ec6aeb2df..7e027a65eec3a 100644 --- a/pandas/tests/extension/json/test_json.py +++ b/pandas/tests/extension/json/test_json.py @@ -3,8 +3,6 @@ import pytest -from pandas.compat import PY36 - import pandas as pd from pandas.tests.extension import base import pandas.util.testing as tm @@ -180,9 +178,6 @@ def test_fillna_frame(self): unhashable = pytest.mark.skip(reason="Unhashable") -unstable = pytest.mark.skipif( - not PY36, reason="Dictionary order unstable" # 3.6 or higher -) class TestReduce(base.BaseNoReduceTests): @@ -199,20 +194,16 @@ def test_sort_values_frame(self): # TODO (EA.factorize): see if _values_for_factorize allows this. pass - @unstable def test_argsort(self, data_for_sorting): super().test_argsort(data_for_sorting) - @unstable def test_argsort_missing(self, data_missing_for_sorting): super().test_argsort_missing(data_missing_for_sorting) - @unstable @pytest.mark.parametrize("ascending", [True, False]) def test_sort_values(self, data_for_sorting, ascending): super().test_sort_values(data_for_sorting, ascending) - @unstable @pytest.mark.parametrize("ascending", [True, False]) def test_sort_values_missing(self, data_missing_for_sorting, ascending): super().test_sort_values_missing(data_missing_for_sorting, ascending) @@ -280,7 +271,6 @@ def test_groupby_extension_apply(self): we'll be able to dispatch unique. """ - @unstable @pytest.mark.parametrize("as_index", [True, False]) def test_groupby_extension_agg(self, as_index, data_for_grouping): super().test_groupby_extension_agg(as_index, data_for_grouping) diff --git a/pandas/tests/frame/test_constructors.py b/pandas/tests/frame/test_constructors.py index 1d030bbc75521..77a7783deeee3 100644 --- a/pandas/tests/frame/test_constructors.py +++ b/pandas/tests/frame/test_constructors.py @@ -8,7 +8,7 @@ import numpy.ma.mrecords as mrecords import pytest -from pandas.compat import PY36, is_platform_little_endian +from pandas.compat import is_platform_little_endian from pandas.core.dtypes.cast import construct_1d_object_array_from_listlike from pandas.core.dtypes.common import is_integer_dtype @@ -387,7 +387,6 @@ def test_constructor_dict_nan_tuple_key(self, value): result = DataFrame(data, index=idx, columns=cols) tm.assert_frame_equal(result, expected) - @pytest.mark.skipif(not PY36, reason="Insertion order for Python>=3.6") def test_constructor_dict_order_insertion(self): datetime_series = tm.makeTimeSeries(nper=30) datetime_series_short = tm.makeTimeSeries(nper=25) @@ -399,18 +398,6 @@ def test_constructor_dict_order_insertion(self): expected = DataFrame(data=d, columns=list("ba")) tm.assert_frame_equal(frame, expected) - @pytest.mark.skipif(PY36, reason="order by value for Python<3.6") - def test_constructor_dict_order_by_values(self): - datetime_series = tm.makeTimeSeries(nper=30) - datetime_series_short = tm.makeTimeSeries(nper=25) - - # GH19018 - # initialization ordering: by value if python<3.6 - d = {"b": datetime_series_short, "a": datetime_series} - frame = DataFrame(data=d) - expected = DataFrame(data=d, columns=list("ab")) - tm.assert_frame_equal(frame, expected) - def test_constructor_multi_index(self): # GH 4078 # construction error with mi and all-nan frame @@ -1373,7 +1360,7 @@ def test_constructor_list_of_dict_order(self): } ) result = DataFrame(data) - tm.assert_frame_equal(result, expected, check_like=not PY36) + tm.assert_frame_equal(result, expected) def test_constructor_orient(self, float_string_frame): data_dict = float_string_frame.T._series diff --git a/pandas/tests/frame/test_mutate_columns.py b/pandas/tests/frame/test_mutate_columns.py index 7feb55f2fac09..8c0dd67af4e7d 100644 --- a/pandas/tests/frame/test_mutate_columns.py +++ b/pandas/tests/frame/test_mutate_columns.py @@ -3,8 +3,6 @@ import numpy as np import pytest -from pandas.compat import PY36 - from pandas import DataFrame, Index, MultiIndex, Series import pandas.util.testing as tm @@ -60,10 +58,7 @@ def test_assign_order(self): df = DataFrame([[1, 2], [3, 4]], columns=["A", "B"]) result = df.assign(D=df.A + df.B, C=df.A - df.B) - if PY36: - expected = DataFrame([[1, 2, 3, -1], [3, 4, 7, -1]], columns=list("ABDC")) - else: - expected = DataFrame([[1, 2, -1, 3], [3, 4, -1, 7]], columns=list("ABCD")) + expected = DataFrame([[1, 2, 3, -1], [3, 4, 7, -1]], columns=list("ABDC")) tm.assert_frame_equal(result, expected) result = df.assign(C=df.A - df.B, D=df.A + df.B) @@ -80,25 +75,6 @@ def test_assign_bad(self): with pytest.raises(AttributeError): df.assign(C=df.A, D=df.A + df.C) - @pytest.mark.skipif( - PY36, - reason="""Issue #14207: valid for python - 3.6 and above""", - ) - def test_assign_dependent_old_python(self): - df = DataFrame({"A": [1, 2, 3], "B": [4, 5, 6]}) - - # Key C does not exist at definition time of df - with pytest.raises(KeyError, match="^'C'$"): - df.assign(C=lambda df: df.A, D=lambda df: df["A"] + df["C"]) - with pytest.raises(KeyError, match="^'C'$"): - df.assign(C=df.A, D=lambda x: x["A"] + x["C"]) - - @pytest.mark.skipif( - not PY36, - reason="""Issue #14207: not valid for - python 3.5 and below""", - ) def test_assign_dependent(self): df = DataFrame({"A": [1, 2], "B": [3, 4]}) diff --git a/pandas/tests/groupby/aggregate/test_aggregate.py b/pandas/tests/groupby/aggregate/test_aggregate.py index c03ffe317083c..a478bf19d0f10 100644 --- a/pandas/tests/groupby/aggregate/test_aggregate.py +++ b/pandas/tests/groupby/aggregate/test_aggregate.py @@ -8,7 +8,7 @@ import pytest import pandas as pd -from pandas import DataFrame, Index, MultiIndex, Series, compat, concat +from pandas import DataFrame, Index, MultiIndex, Series, concat from pandas.core.base import SpecificationError from pandas.core.groupby.generic import _make_unique, _maybe_mangle_lambdas from pandas.core.groupby.grouper import Grouping @@ -361,9 +361,7 @@ def test_series_named_agg(self): tm.assert_frame_equal(result, expected) result = gr.agg(b="min", a="sum") - # sort for 35 and earlier - if compat.PY36: - expected = expected[["b", "a"]] + expected = expected[["b", "a"]] tm.assert_frame_equal(result, expected) def test_no_args_raises(self): @@ -425,8 +423,6 @@ def test_agg_relabel(self): index=pd.Index(["a", "b"], name="group"), columns=["b_min", "a_min", "a_mean", "a_max", "b_max", "a_98"], ) - if not compat.PY36: - expected = expected[["a_98", "a_max", "a_mean", "a_min", "b_max", "b_min"]] tm.assert_frame_equal(result, expected) def test_agg_relabel_non_identifier(self): diff --git a/pandas/tests/indexes/test_base.py b/pandas/tests/indexes/test_base.py index e43d340a46d9f..fe9953341fdae 100644 --- a/pandas/tests/indexes/test_base.py +++ b/pandas/tests/indexes/test_base.py @@ -11,7 +11,6 @@ import pandas._config.config as cf from pandas._libs.tslib import Timestamp -from pandas.compat import PY36 from pandas.compat.numpy import np_datetime64_compat from pandas.core.dtypes.common import is_unsigned_integer_dtype @@ -1616,11 +1615,7 @@ def test_get_loc(self, method): def test_get_loc_raises_bad_label(self, method): index = pd.Index([0, 1, 2]) if method: - # Messages vary across versions - if PY36: - msg = "not supported between" - else: - msg = "unorderable types" + msg = "not supported between" else: msg = "invalid key" @@ -2444,21 +2439,13 @@ def create_index(self): def test_argsort(self): index = self.create_index() - if PY36: - with pytest.raises(TypeError, match="'>|<' not supported"): - index.argsort() - else: - with pytest.raises(TypeError, match="unorderable types"): - index.argsort() + with pytest.raises(TypeError, match="'>|<' not supported"): + index.argsort() def test_numpy_argsort(self): index = self.create_index() - if PY36: - with pytest.raises(TypeError, match="'>|<' not supported"): - np.argsort(index) - else: - with pytest.raises(TypeError, match="unorderable types"): - np.argsort(index) + with pytest.raises(TypeError, match="'>|<' not supported"): + np.argsort(index) def test_copy_name(self): # Check that "name" argument passed at initialization is honoured diff --git a/pandas/tests/indexing/test_indexing.py b/pandas/tests/indexing/test_indexing.py index d6d3763981131..fc5753ec2955c 100644 --- a/pandas/tests/indexing/test_indexing.py +++ b/pandas/tests/indexing/test_indexing.py @@ -7,7 +7,6 @@ import numpy as np import pytest -from pandas.compat import PY36 from pandas.errors import AbstractMethodError from pandas.core.dtypes.common import is_float_dtype, is_integer_dtype @@ -222,7 +221,7 @@ def test_setitem_dtype_upcast(self): expected = DataFrame( [{"a": 1, "b": np.nan, "c": "foo"}, {"a": 3, "b": 2, "c": np.nan}] ) - tm.assert_frame_equal(df, expected, check_like=not PY36) + tm.assert_frame_equal(df, expected) # GH10280 df = DataFrame( diff --git a/pandas/tests/internals/test_internals.py b/pandas/tests/internals/test_internals.py index ee7fca6ec7672..fa7a98c617677 100644 --- a/pandas/tests/internals/test_internals.py +++ b/pandas/tests/internals/test_internals.py @@ -1,10 +1,8 @@ from collections import OrderedDict from datetime import date, datetime -from distutils.version import LooseVersion import itertools import operator import re -import sys import numpy as np import pytest @@ -26,9 +24,6 @@ from pandas.core.internals import BlockManager, SingleBlockManager, make_block import pandas.util.testing as tm -# in 3.6.1 a c-api slicing function changed, see src/compat_helper.h -PY361 = LooseVersion(sys.version) >= LooseVersion("3.6.1") - @pytest.fixture def mgr(): @@ -1096,10 +1091,6 @@ def assert_as_slice_equals(arr, slc): assert_as_slice_equals([2, 1], slice(2, 0, -1)) - if not PY361: - assert_as_slice_equals([2, 1, 0], slice(2, None, -1)) - assert_as_slice_equals([100, 0], slice(100, None, -100)) - def test_not_slice_like_arrays(self): def assert_not_slice_like(arr): assert not BlockPlacement(arr).is_slice_like @@ -1119,10 +1110,6 @@ def test_slice_iter(self): assert list(BlockPlacement(slice(0, 0))) == [] assert list(BlockPlacement(slice(3, 0))) == [] - if not PY361: - assert list(BlockPlacement(slice(3, 0, -1))) == [3, 2, 1] - assert list(BlockPlacement(slice(3, None, -1))) == [3, 2, 1, 0] - def test_slice_to_array_conversion(self): def assert_as_array_equals(slc, asarray): tm.assert_numpy_array_equal( @@ -1135,10 +1122,6 @@ def assert_as_array_equals(slc, asarray): assert_as_array_equals(slice(3, 0, -1), [3, 2, 1]) - if not PY361: - assert_as_array_equals(slice(3, None, -1), [3, 2, 1, 0]) - assert_as_array_equals(slice(31, None, -10), [31, 21, 11, 1]) - def test_blockplacement_add(self): bpl = BlockPlacement(slice(0, 5)) assert bpl.add(1).as_slice == slice(1, 6, 1) @@ -1168,14 +1151,6 @@ def assert_add_equals(val, inc, result): with pytest.raises(ValueError): BlockPlacement([1, 2, 4]).add(-10) - if not PY361: - assert_add_equals(slice(3, 0, -1), -1, [2, 1, 0]) - assert_add_equals(slice(2, None, -1), 0, [2, 1, 0]) - assert_add_equals(slice(2, None, -1), 10, [12, 11, 10]) - - with pytest.raises(ValueError): - BlockPlacement(slice(2, None, -1)).add(-1) - class DummyElement: def __init__(self, value, dtype): diff --git a/pandas/tests/io/excel/test_writers.py b/pandas/tests/io/excel/test_writers.py index 1bc4ad3e7867a..a7730e079a1bb 100644 --- a/pandas/tests/io/excel/test_writers.py +++ b/pandas/tests/io/excel/test_writers.py @@ -6,7 +6,6 @@ import numpy as np import pytest -from pandas.compat import PY36 import pandas.util._test_decorators as td import pandas as pd @@ -1262,7 +1261,6 @@ def check_called(func): @td.skip_if_no("xlrd") @td.skip_if_no("openpyxl") -@pytest.mark.skipif(not PY36, reason="requires fspath") class TestFSPath: def test_excelfile_fspath(self): with tm.ensure_clean("foo.xlsx") as path: diff --git a/pandas/tests/io/formats/test_format.py b/pandas/tests/io/formats/test_format.py index 704de378b0909..0f4a7a33dd115 100644 --- a/pandas/tests/io/formats/test_format.py +++ b/pandas/tests/io/formats/test_format.py @@ -18,7 +18,7 @@ import pytest import pytz -from pandas.compat import PY36, is_platform_32bit, is_platform_windows +from pandas.compat import is_platform_32bit, is_platform_windows import pandas as pd from pandas import ( @@ -62,10 +62,7 @@ def filepath_or_buffer(filepath_or_buffer_id, tmp_path): yield buf assert not buf.closed else: - if PY36: - assert isinstance(tmp_path, Path) - else: - assert hasattr(tmp_path, "__fspath__") + assert isinstance(tmp_path, Path) if filepath_or_buffer_id == "pathlike": yield tmp_path / "foo" else: diff --git a/pandas/tests/io/json/test_normalize.py b/pandas/tests/io/json/test_normalize.py index a3ca61cb1eb63..c71c52bce87b8 100644 --- a/pandas/tests/io/json/test_normalize.py +++ b/pandas/tests/io/json/test_normalize.py @@ -3,8 +3,6 @@ import numpy as np import pytest -from pandas.compat import PY36 - from pandas import DataFrame, Index import pandas.util.testing as tm @@ -382,7 +380,7 @@ def test_missing_field(self, author_missing_data): }, ] expected = DataFrame(ex_data) - tm.assert_frame_equal(result, expected, check_like=not PY36) + tm.assert_frame_equal(result, expected) @pytest.mark.parametrize( "max_level,expected", @@ -524,7 +522,7 @@ def test_missing_meta(self, missing_metadata): columns = ["city", "number", "state", "street", "zip", "name"] columns = ["number", "street", "city", "state", "zip", "name"] expected = DataFrame(ex_data, columns=columns) - tm.assert_frame_equal(result, expected, check_like=not PY36) + tm.assert_frame_equal(result, expected) def test_donot_drop_nonevalues(self): # GH21356 diff --git a/pandas/tests/io/parser/test_common.py b/pandas/tests/io/parser/test_common.py index 6e6c31bc5b972..590f26a76802a 100644 --- a/pandas/tests/io/parser/test_common.py +++ b/pandas/tests/io/parser/test_common.py @@ -2160,10 +2160,6 @@ def test_suppress_error_output(all_parsers, capsys): assert captured.err == "" -@pytest.mark.skipif( - compat.is_platform_windows() and not compat.PY36, - reason="On Python < 3.6 won't pass on Windows", -) @pytest.mark.parametrize("filename", ["sé-es-vé.csv", "ru-sй.csv", "中文文件名.csv"]) def test_filename_with_special_chars(all_parsers, filename): # see gh-15086. diff --git a/pandas/tests/io/pytables/test_store.py b/pandas/tests/io/pytables/test_store.py index f9d525399bde3..a43da75005a65 100644 --- a/pandas/tests/io/pytables/test_store.py +++ b/pandas/tests/io/pytables/test_store.py @@ -9,7 +9,7 @@ import numpy as np import pytest -from pandas.compat import PY36, is_platform_little_endian, is_platform_windows +from pandas.compat import is_platform_little_endian, is_platform_windows import pandas.util._test_decorators as td from pandas.core.dtypes.common import is_categorical_dtype @@ -4711,7 +4711,6 @@ def test_read_hdf_series_mode_r(self, format, setup_path): result = pd.read_hdf(path, key="data", mode="r") tm.assert_series_equal(result, series) - @pytest.mark.skipif(not PY36, reason="Need python 3.6") def test_fspath(self): with tm.ensure_clean("foo.h5") as path: with pd.HDFStore(path) as store: diff --git a/pandas/tests/reshape/test_concat.py b/pandas/tests/reshape/test_concat.py index 46dafbc4e1ec8..323b3126c2461 100644 --- a/pandas/tests/reshape/test_concat.py +++ b/pandas/tests/reshape/test_concat.py @@ -27,7 +27,6 @@ isna, read_csv, ) -import pandas.core.common as com from pandas.tests.extension.decimal import to_decimal import pandas.util.testing as tm @@ -1264,7 +1263,7 @@ def test_concat_dict(self): "qux": DataFrame(np.random.randn(4, 3)), } - sorted_keys = com.dict_keys_to_ordered_list(frames) + sorted_keys = list(frames.keys()) result = concat(frames) expected = concat([frames[k] for k in sorted_keys], keys=sorted_keys) diff --git a/pandas/tests/scalar/timestamp/test_unary_ops.py b/pandas/tests/scalar/timestamp/test_unary_ops.py index dffb957b8f3b0..db63e0bf9cd30 100644 --- a/pandas/tests/scalar/timestamp/test_unary_ops.py +++ b/pandas/tests/scalar/timestamp/test_unary_ops.py @@ -7,7 +7,6 @@ from pandas._libs.tslibs import conversion from pandas._libs.tslibs.frequencies import INVALID_FREQ_ERR_MSG -from pandas.compat import PY36 import pandas.util._test_decorators as td from pandas import NaT, Timestamp @@ -375,7 +374,6 @@ def test_replace_dst_border(self): expected = Timestamp("2013-11-3 03:00:00", tz="America/Chicago") assert result == expected - @pytest.mark.skipif(not PY36, reason="Fold not available until PY3.6") @pytest.mark.parametrize("fold", [0, 1]) @pytest.mark.parametrize("tz", ["dateutil/Europe/London", "Europe/London"]) def test_replace_dst_fold(self, fold, tz): diff --git a/pandas/tests/series/test_constructors.py b/pandas/tests/series/test_constructors.py index 4cbade2669cc6..34b11a0d008aa 100644 --- a/pandas/tests/series/test_constructors.py +++ b/pandas/tests/series/test_constructors.py @@ -7,7 +7,6 @@ from pandas._libs import lib from pandas._libs.tslib import iNaT -from pandas.compat import PY36 from pandas.core.dtypes.common import is_categorical_dtype, is_datetime64tz_dtype from pandas.core.dtypes.dtypes import CategoricalDtype, ordered_sentinel @@ -1048,10 +1047,7 @@ def test_constructor_dict_order(self): # order by value d = {"b": 1, "a": 0, "c": 2} result = Series(d) - if PY36: - expected = Series([1, 0, 2], index=list("bac")) - else: - expected = Series([0, 1, 2], index=list("abc")) + expected = Series([1, 0, 2], index=list("bac")) tm.assert_series_equal(result, expected) @pytest.mark.parametrize("value", [2, np.nan, None, float("nan")]) diff --git a/pandas/tests/test_downstream.py b/pandas/tests/test_downstream.py index fb0511f8902f7..dc88ebe1f7f8e 100644 --- a/pandas/tests/test_downstream.py +++ b/pandas/tests/test_downstream.py @@ -8,8 +8,6 @@ import numpy as np # noqa import pytest -from pandas.compat import PY36 - from pandas import DataFrame, Series import pandas.util.testing as tm @@ -18,19 +16,10 @@ def import_module(name): # we *only* want to skip if the module is truly not available # and NOT just an actual import error because of pandas changes - if PY36: - try: - return importlib.import_module(name) - except ModuleNotFoundError: # noqa - pytest.skip("skipping as {} not available".format(name)) - - else: - try: - return importlib.import_module(name) - except ImportError as e: - if "No module named" in str(e) and name in str(e): - pytest.skip("skipping as {} not available".format(name)) - raise + try: + return importlib.import_module(name) + except ModuleNotFoundError: # noqa + pytest.skip("skipping as {} not available".format(name)) @pytest.fixture