diff --git a/pandas/_libs/tslibs/parsing.pyx b/pandas/_libs/tslibs/parsing.pyx index 1741ff24b1ac8..e3e9863adcbd3 100644 --- a/pandas/_libs/tslibs/parsing.pyx +++ b/pandas/_libs/tslibs/parsing.pyx @@ -11,8 +11,6 @@ from cpython.datetime cimport datetime import numpy as np -import six - # dateutil compat from dateutil.tz import (tzoffset, tzlocal as _dateutil_tzlocal, @@ -526,14 +524,8 @@ def try_parse_datetime_components(object[:] years, # Copyright (c) 2017 - dateutil contributors class _timelex(object): def __init__(self, instream): - if six.PY2: - # In Python 2, we can't duck type properly because unicode has - # a 'decode' function, and we'd be double-decoding - if isinstance(instream, (bytes, bytearray)): - instream = instream.decode() - else: - if getattr(instream, 'decode', None) is not None: - instream = instream.decode() + if getattr(instream, 'decode', None) is not None: + instream = instream.decode() if isinstance(instream, str): self.stream = instream diff --git a/pandas/_version.py b/pandas/_version.py index 2e46beff13e35..91f6c5d788d0a 100644 --- a/pandas/_version.py +++ b/pandas/_version.py @@ -14,8 +14,6 @@ import sys from typing import Callable, Dict -from pandas.compat import PY3 - def get_keywords(): # these strings will be replaced by git during git-archive. @@ -84,9 +82,7 @@ def run_command(commands, args, cwd=None, verbose=False, hide_stderr=False): if verbose: print("unable to find command, tried %s" % (commands,)) return None - stdout = p.communicate()[0].strip() - if PY3: - stdout = stdout.decode() + stdout = p.communicate()[0].strip().decode() if p.returncode != 0: if verbose: print("unable to run {dispcmd} (error)".format(dispcmd=dispcmd)) diff --git a/pandas/compat/__init__.py b/pandas/compat/__init__.py index b1991e3fb1162..3312c6eaa86c3 100644 --- a/pandas/compat/__init__.py +++ b/pandas/compat/__init__.py @@ -2,9 +2,9 @@ compat ====== -Cross-compatible functions for Python 2 and 3. +Cross-compatible functions for different versions of Python. -Key items to import for 2/3 compatible code: +Key items to import for compatible code: * lists: lrange(), lmap(), lzip(), lfilter() * iterable method compatibility: iteritems, iterkeys, itervalues * Uses the original method if available, otherwise uses items, keys, values. @@ -23,8 +23,6 @@ import platform import struct -PY2 = sys.version_info[0] == 2 -PY3 = sys.version_info[0] >= 3 PY36 = sys.version_info >= (3, 6) PY37 = sys.version_info >= (3, 7) PYPY = platform.python_implementation() == 'PyPy' @@ -47,25 +45,16 @@ def lfilter(*args, **kwargs): return list(filter(*args, **kwargs)) -if PY2: - def iteritems(obj, **kw): - return obj.iteritems(**kw) +def iteritems(obj, **kw): + return iter(obj.items(**kw)) - def iterkeys(obj, **kw): - return obj.iterkeys(**kw) - def itervalues(obj, **kw): - return obj.itervalues(**kw) +def iterkeys(obj, **kw): + return iter(obj.keys(**kw)) -else: - def iteritems(obj, **kw): - return iter(obj.items(**kw)) - - def iterkeys(obj, **kw): - return iter(obj.keys(**kw)) - def itervalues(obj, **kw): - return iter(obj.values(**kw)) +def itervalues(obj, **kw): + return iter(obj.values(**kw)) # ---------------------------------------------------------------------------- # functions largely based / taken from the six module @@ -75,42 +64,33 @@ def itervalues(obj, **kw): # found at https://bitbucket.org/gutworth/six -if PY3: - def to_str(s): - """ - Convert bytes and non-string into Python 3 str - """ - if isinstance(s, bytes): - s = s.decode('utf-8') - elif not isinstance(s, str): - s = str(s) - return s - - def set_function_name(f, name, cls): - """ Bind the name/qualname attributes of the function """ - f.__name__ = name - f.__qualname__ = '{klass}.{name}'.format( - klass=cls.__name__, - name=name) - f.__module__ = cls.__module__ - return f -else: - def to_str(s): - """ - Convert unicode and non-string into Python 2 str - """ - if not isinstance(s, basestring): - s = str(s) - return s +def to_str(s): + """ + Convert bytes and non-string into Python 3 str + """ + if isinstance(s, bytes): + s = s.decode('utf-8') + elif not isinstance(s, str): + s = str(s) + return s - def set_function_name(f, name, cls): - """ Bind the name attributes of the function """ - f.__name__ = name - return f + +def set_function_name(f, name, cls): + """ + Bind the name/qualname attributes of the function + """ + f.__name__ = name + f.__qualname__ = '{klass}.{name}'.format( + klass=cls.__name__, + name=name) + f.__module__ = cls.__module__ + return f def add_metaclass(metaclass): - """Class decorator for creating a class with a metaclass.""" + """ + Class decorator for creating a class with a metaclass. + """ def wrapper(cls): orig_vars = cls.__dict__.copy() orig_vars.pop('__dict__', None) @@ -121,22 +101,14 @@ def wrapper(cls): return wrapper -if PY3: - def raise_with_traceback(exc, traceback=Ellipsis): - if traceback == Ellipsis: - _, _, traceback = sys.exc_info() - raise exc.with_traceback(traceback) -else: - # this version of raise is a syntax error in Python 3 - exec(""" def raise_with_traceback(exc, traceback=Ellipsis): + """ + Raise exception with existing traceback. + If traceback is not passed, uses sys.exc_info() to get traceback. + """ if traceback == Ellipsis: _, _, traceback = sys.exc_info() - raise exc, None, traceback -""") - -raise_with_traceback.__doc__ = """Raise exception with existing traceback. -If traceback is not passed, uses sys.exc_info() to get traceback.""" + raise exc.with_traceback(traceback) # dateutil minimum version diff --git a/pandas/conftest.py b/pandas/conftest.py index 1cb518f426299..462ee10f11975 100644 --- a/pandas/conftest.py +++ b/pandas/conftest.py @@ -9,7 +9,6 @@ import pytest from pytz import FixedOffset, utc -from pandas.compat import PY3 import pandas.util._test_decorators as td import pandas as pd @@ -134,8 +133,6 @@ def observed(request): '__truediv__', '__rtruediv__', '__pow__', '__rpow__', '__mod__', '__rmod__'] -if not PY3: - _all_arithmetic_operators.extend(['__div__', '__rdiv__']) @pytest.fixture(params=_all_arithmetic_operators) @@ -248,12 +245,7 @@ def datetime_tz_utc(): return timezone.utc -utc_objs = ['utc', 'dateutil/UTC', utc, tzutc()] -if PY3: - utc_objs.append(timezone.utc) - - -@pytest.fixture(params=utc_objs) +@pytest.fixture(params=['utc', 'dateutil/UTC', utc, tzutc(), timezone.utc]) def utc_fixture(request): """ Fixture to provide variants of UTC timezone strings and tzinfo objects @@ -406,9 +398,9 @@ def tz_aware_fixture(request): OBJECT_DTYPES = [object, 'object'] ALL_REAL_DTYPES = FLOAT_DTYPES + ALL_INT_DTYPES -ALL_NUMPY_DTYPES = (ALL_REAL_DTYPES + COMPLEX_DTYPES + STRING_DTYPES - + DATETIME_DTYPES + TIMEDELTA_DTYPES + BOOL_DTYPES - + OBJECT_DTYPES + BYTES_DTYPES * PY3) # bytes only for PY3 +ALL_NUMPY_DTYPES = (ALL_REAL_DTYPES + COMPLEX_DTYPES + STRING_DTYPES + + DATETIME_DTYPES + TIMEDELTA_DTYPES + BOOL_DTYPES + + OBJECT_DTYPES + BYTES_DTYPES) @pytest.fixture(params=STRING_DTYPES) @@ -559,8 +551,7 @@ def any_numpy_dtype(request): # categoricals are handled separately _any_skipna_inferred_dtype = [ ('string', ['a', np.nan, 'c']), - ('unicode' if not PY3 else 'string', ['a', np.nan, 'c']), - ('bytes' if PY3 else 'string', [b'a', np.nan, b'c']), + ('bytes', [b'a', np.nan, b'c']), ('empty', [np.nan, np.nan, np.nan]), ('empty', []), ('mixed-integer', ['a', np.nan, 2]), @@ -592,9 +583,8 @@ def any_skipna_inferred_dtype(request): The covered (inferred) types are: * 'string' - * 'unicode' (if PY2) * 'empty' - * 'bytes' (if PY3) + * 'bytes' * 'mixed' * 'mixed-integer' * 'mixed-integer-float' diff --git a/pandas/core/arrays/base.py b/pandas/core/arrays/base.py index 846eb442ef816..b487cbfe78a86 100644 --- a/pandas/core/arrays/base.py +++ b/pandas/core/arrays/base.py @@ -10,7 +10,7 @@ import numpy as np -from pandas.compat import PY3, set_function_name +from pandas.compat import set_function_name from pandas.compat.numpy import function as nv from pandas.errors import AbstractMethodError from pandas.util._decorators import Appender, Substitution @@ -991,10 +991,6 @@ def _add_arithmetic_ops(cls): cls.__rfloordiv__ = cls._create_arithmetic_method(ops.rfloordiv) cls.__truediv__ = cls._create_arithmetic_method(operator.truediv) cls.__rtruediv__ = cls._create_arithmetic_method(ops.rtruediv) - if not PY3: - cls.__div__ = cls._create_arithmetic_method(operator.div) - cls.__rdiv__ = cls._create_arithmetic_method(ops.rdiv) - cls.__divmod__ = cls._create_arithmetic_method(divmod) cls.__rdivmod__ = cls._create_arithmetic_method(ops.rdivmod) diff --git a/pandas/core/arrays/sparse.py b/pandas/core/arrays/sparse.py index 1184cf1ee71f2..2eb33d6d2c50f 100644 --- a/pandas/core/arrays/sparse.py +++ b/pandas/core/arrays/sparse.py @@ -1593,8 +1593,6 @@ def __array_ufunc__(self, ufunc, method, *inputs, **kwargs): special = {'add', 'sub', 'mul', 'pow', 'mod', 'floordiv', 'truediv', 'divmod', 'eq', 'ne', 'lt', 'gt', 'le', 'ge', 'remainder'} - if compat.PY2: - special.add('div') aliases = { 'subtract': 'sub', 'multiply': 'mul', diff --git a/pandas/core/arrays/timedeltas.py b/pandas/core/arrays/timedeltas.py index d1bf59218edfe..6644b8144196b 100644 --- a/pandas/core/arrays/timedeltas.py +++ b/pandas/core/arrays/timedeltas.py @@ -566,10 +566,6 @@ def __rtruediv__(self, other): .format(dtype=other.dtype, cls=type(self).__name__)) - if compat.PY2: - __div__ = __truediv__ - __rdiv__ = __rtruediv__ - def __floordiv__(self, other): if isinstance(other, (ABCSeries, ABCDataFrame, ABCIndexClass)): return NotImplemented diff --git a/pandas/core/base.py b/pandas/core/base.py index 9a0a4e3e9ca03..d4294e59cc845 100644 --- a/pandas/core/base.py +++ b/pandas/core/base.py @@ -34,10 +34,8 @@ class StringMixin(object): - """implements string methods so long as object defines a `__unicode__` - method. - - Handles Python2/3 compatibility transparently. + """ + Implements string methods so long as object defines a `__unicode__` method. """ # side note - this could be made into a metaclass if more than one # object needs @@ -51,21 +49,12 @@ def __unicode__(self): def __str__(self): """ Return a string representation for a particular Object - - Invoked by str(df) in both py2/py3. - Yields Bytestring in Py2, Unicode String in py3. """ - - if compat.PY3: - return self.__unicode__() - return self.__bytes__() + return self.__unicode__() def __bytes__(self): """ Return a string representation for a particular object. - - Invoked by bytes(obj) in py3 only. - Yields a bytestring in both py2/py3. """ from pandas._config import get_option @@ -75,8 +64,6 @@ def __bytes__(self): def __repr__(self): """ Return a string representation for a particular object. - - Yields Bytestring in Py2, Unicode String in py3. """ return str(self) @@ -93,9 +80,6 @@ def _constructor(self): def __unicode__(self): """ Return a string representation for a particular object. - - Invoked by unicode(obj) in py2 only. Yields a Unicode String in both - py2/py3. """ # Should be overwritten by base classes return object.__repr__(self) diff --git a/pandas/core/computation/ops.py b/pandas/core/computation/ops.py index 298284069305e..baeb2af7d843e 100644 --- a/pandas/core/computation/ops.py +++ b/pandas/core/computation/ops.py @@ -9,7 +9,6 @@ import numpy as np from pandas._libs.tslibs import Timestamp -from pandas.compat import PY3 from pandas.core.dtypes.common import is_list_like, is_scalar @@ -272,8 +271,8 @@ def _not_in(x, y): _bool_ops_dict = dict(zip(_bool_ops_syms, _bool_ops_funcs)) _arith_ops_syms = '+', '-', '*', '/', '**', '//', '%' -_arith_ops_funcs = (op.add, op.sub, op.mul, op.truediv if PY3 else op.div, - op.pow, op.floordiv, op.mod) +_arith_ops_funcs = (op.add, op.sub, op.mul, op.truediv, op.pow, op.floordiv, + op.mod) _arith_ops_dict = dict(zip(_arith_ops_syms, _arith_ops_funcs)) _special_case_arith_ops_syms = '**', '//', '%' @@ -471,10 +470,9 @@ def __init__(self, lhs, rhs, truediv, *args, **kwargs): lhs.return_type, rhs.return_type)) - if truediv or PY3: - # do not upcast float32s to float64 un-necessarily - acceptable_dtypes = [np.float32, np.float_] - _cast_inplace(com.flatten(self), acceptable_dtypes, np.float_) + # do not upcast float32s to float64 un-necessarily + acceptable_dtypes = [np.float32, np.float_] + _cast_inplace(com.flatten(self), acceptable_dtypes, np.float_) _unary_ops_syms = '+', '-', '~', 'not' diff --git a/pandas/core/dtypes/cast.py b/pandas/core/dtypes/cast.py index 1d09f7434408f..78754b13e1705 100644 --- a/pandas/core/dtypes/cast.py +++ b/pandas/core/dtypes/cast.py @@ -6,7 +6,7 @@ from pandas._libs import lib, tslib, tslibs from pandas._libs.tslibs import NaT, OutOfBoundsDatetime, Period, iNaT -from pandas.compat import PY3, to_str +from pandas.compat import to_str from .common import ( _INT64_DTYPE, _NS_DTYPE, _POSSIBLY_CAST_DTYPES, _TD_DTYPE, ensure_int8, @@ -664,9 +664,7 @@ def astype_nansafe(arr, dtype, copy=True, skipna=False): elif dtype == np.int64: return arr.view(dtype) - # in py3, timedelta64[ns] are int64 - if ((PY3 and dtype not in [_INT64_DTYPE, _TD_DTYPE]) or - (not PY3 and dtype != _TD_DTYPE)): + if dtype not in [_INT64_DTYPE, _TD_DTYPE]: # allow frequency conversions # we return a float here! diff --git a/pandas/core/dtypes/common.py b/pandas/core/dtypes/common.py index df9e036848df8..26255c5c4c7b0 100644 --- a/pandas/core/dtypes/common.py +++ b/pandas/core/dtypes/common.py @@ -5,7 +5,7 @@ from pandas._libs import algos, lib from pandas._libs.tslibs import conversion -from pandas.compat import PY3, PY36 +from pandas.compat import PY36 from pandas.core.dtypes.dtypes import ( CategoricalDtype, DatetimeTZDtype, ExtensionDtype, IntervalDtype, @@ -1274,9 +1274,7 @@ def _is_unorderable_exception(e): if PY36: return "'>' not supported between instances of" in str(e) - elif PY3: - return 'unorderable' in str(e) - return False + return 'unorderable' in str(e) def is_numeric_v_string_like(a, b): diff --git a/pandas/core/dtypes/dtypes.py b/pandas/core/dtypes/dtypes.py index f0dd70886dc06..5624f81b48c42 100644 --- a/pandas/core/dtypes/dtypes.py +++ b/pandas/core/dtypes/dtypes.py @@ -11,8 +11,6 @@ from pandas.core.dtypes.generic import ( ABCCategoricalIndex, ABCDateOffset, ABCIndexClass) -from pandas import compat - from .base import ExtensionDtype, _DtypeOpsMixin from .inference import is_list_like @@ -122,21 +120,12 @@ def __unicode__(self): def __str__(self): """ Return a string representation for a particular Object - - Invoked by str(df) in both py2/py3. - Yields Bytestring in Py2, Unicode String in py3. """ - - if compat.PY3: - return self.__unicode__() - return self.__bytes__() + return self.__unicode__() def __bytes__(self): """ Return a string representation for a particular object. - - Invoked by bytes(obj) in py3 only. - Yields a bytestring in both py2/py3. """ from pandas._config import get_option @@ -146,8 +135,6 @@ def __bytes__(self): def __repr__(self): """ Return a string representation for a particular object. - - Yields Bytestring in Py2, Unicode String in py3. """ return str(self) diff --git a/pandas/core/dtypes/inference.py b/pandas/core/dtypes/inference.py index 09d585ee3899b..0dc6ddbde9a77 100644 --- a/pandas/core/dtypes/inference.py +++ b/pandas/core/dtypes/inference.py @@ -7,7 +7,7 @@ import numpy as np from pandas._libs import lib -from pandas.compat import PY2, re_type +from pandas.compat import re_type is_bool = lib.is_bool @@ -146,12 +146,7 @@ def is_iterator(obj): if not hasattr(obj, '__iter__'): return False - if PY2: - return hasattr(obj, 'next') - else: - # Python 3 generators have - # __next__ instead of next - return hasattr(obj, '__next__') + return hasattr(obj, '__next__') def is_file_like(obj): diff --git a/pandas/core/indexes/base.py b/pandas/core/indexes/base.py index 1875976a8f931..74112800ba437 100644 --- a/pandas/core/indexes/base.py +++ b/pandas/core/indexes/base.py @@ -5044,9 +5044,6 @@ def _add_numeric_methods_disabled(cls): cls.__rfloordiv__ = make_invalid_op('__rfloordiv__') cls.__truediv__ = make_invalid_op('__truediv__') cls.__rtruediv__ = make_invalid_op('__rtruediv__') - if not compat.PY3: - cls.__div__ = make_invalid_op('__div__') - cls.__rdiv__ = make_invalid_op('__rdiv__') cls.__mod__ = make_invalid_op('__mod__') cls.__divmod__ = make_invalid_op('__divmod__') cls.__neg__ = make_invalid_op('__neg__') @@ -5128,9 +5125,6 @@ def _add_numeric_methods_binary(cls): cls.__truediv__ = _make_arithmetic_op(operator.truediv, cls) cls.__rtruediv__ = _make_arithmetic_op(ops.rtruediv, cls) - if not compat.PY3: - cls.__div__ = _make_arithmetic_op(operator.div, cls) - cls.__rdiv__ = _make_arithmetic_op(ops.rdiv, cls) # TODO: rmod? rdivmod? cls.__mod__ = _make_arithmetic_op(operator.mod, cls) diff --git a/pandas/core/indexes/range.py b/pandas/core/indexes/range.py index ec90e4aa6867c..da6a917c93ba4 100644 --- a/pandas/core/indexes/range.py +++ b/pandas/core/indexes/range.py @@ -726,9 +726,6 @@ def _evaluate_numeric_binop(self, other): step=operator.truediv) cls.__rtruediv__ = _make_evaluate_binop(ops.rtruediv, step=ops.rtruediv) - if not compat.PY3: - cls.__div__ = _make_evaluate_binop(operator.div, step=operator.div) - cls.__rdiv__ = _make_evaluate_binop(ops.rdiv, step=ops.rdiv) RangeIndex._add_numeric_methods() diff --git a/pandas/core/indexes/timedeltas.py b/pandas/core/indexes/timedeltas.py index c3ed26b5b1cca..976130635c990 100644 --- a/pandas/core/indexes/timedeltas.py +++ b/pandas/core/indexes/timedeltas.py @@ -6,7 +6,6 @@ from pandas._libs import ( NaT, Timedelta, index as libindex, join as libjoin, lib) -import pandas.compat as compat from pandas.util._decorators import Appender, Substitution from pandas.core.dtypes.common import ( @@ -299,9 +298,6 @@ def _format_native_types(self, na_rep='NaT', date_format=None, **kwargs): __rdivmod__ = _make_wrapped_arith_op("__rdivmod__") __truediv__ = _make_wrapped_arith_op("__truediv__") __rtruediv__ = _make_wrapped_arith_op("__rtruediv__") - if compat.PY2: - __div__ = __truediv__ - __rdiv__ = __rtruediv__ # Compat for frequency inference, see GH#23789 _is_monotonic_increasing = Index.is_monotonic_increasing diff --git a/pandas/core/ops.py b/pandas/core/ops.py index b7e24ccad3736..8c423e0cf304a 100644 --- a/pandas/core/ops.py +++ b/pandas/core/ops.py @@ -11,7 +11,6 @@ import numpy as np from pandas._libs import algos as libalgos, lib, ops as libops -import pandas.compat as compat from pandas.errors import NullFrequencyError from pandas.util._decorators import Appender @@ -1591,8 +1590,6 @@ def f(self, other): __ifloordiv__=_wrap_inplace_method(new_methods["__floordiv__"]), __imod__=_wrap_inplace_method(new_methods["__mod__"]), __ipow__=_wrap_inplace_method(new_methods["__pow__"]))) - if not compat.PY3: - new_methods["__idiv__"] = _wrap_inplace_method(new_methods["__div__"]) new_methods.update( dict(__iand__=_wrap_inplace_method(new_methods["__and__"]), diff --git a/pandas/core/sorting.py b/pandas/core/sorting.py index c2a66ce608f3f..22715c4f21a38 100644 --- a/pandas/core/sorting.py +++ b/pandas/core/sorting.py @@ -5,7 +5,6 @@ from pandas._libs import algos, hashtable, lib from pandas._libs.hashtable import unique_label_indices -from pandas.compat import PY3 from pandas.core.dtypes.cast import infer_dtype_from_array from pandas.core.dtypes.common import ( @@ -461,7 +460,7 @@ def sort_mixed(values): return np.concatenate([nums, np.asarray(strs, dtype=object)]) sorter = None - if PY3 and lib.infer_dtype(values, skipna=False) == 'mixed-integer': + if lib.infer_dtype(values, skipna=False) == 'mixed-integer': # unorderable in py3 if mixed str/int ordered = sort_mixed(values) else: diff --git a/pandas/core/strings.py b/pandas/core/strings.py index 6a73f2fc22125..aa0a01526cec5 100644 --- a/pandas/core/strings.py +++ b/pandas/core/strings.py @@ -9,7 +9,6 @@ import pandas._libs.lib as lib import pandas._libs.ops as libops -import pandas.compat as compat from pandas.util._decorators import Appender, deprecate_kwarg from pandas.core.dtypes.common import ( @@ -75,11 +74,8 @@ def _map(f, arr, na_mask=False, na_value=np.nan, dtype=object): except (TypeError, AttributeError) as e: # Reraise the exception if callable `f` got wrong number of args. # The user may want to be warned by this, instead of getting NaN - if compat.PY2: - p_err = r'takes (no|(exactly|at (least|most)) ?\d+) arguments?' - else: - p_err = (r'((takes)|(missing)) (?(2)from \d+ to )?\d+ ' - r'(?(3)required )positional arguments?') + p_err = (r'((takes)|(missing)) (?(2)from \d+ to )?\d+ ' + r'(?(3)required )positional arguments?') if len(e.args) >= 1 and re.search(p_err, e.args[0]): raise e @@ -1598,42 +1594,24 @@ def str_wrap(arr, width, **kwargs): return _na_map(lambda s: '\n'.join(tw.wrap(s)), arr) -def str_translate(arr, table, deletechars=None): +def str_translate(arr, table): """ Map all characters in the string through the given mapping table. - Equivalent to standard :meth:`str.translate`. Note that the optional - argument deletechars is only valid if you are using python 2. For python 3, - character deletion should be specified via the table argument. + Equivalent to standard :meth:`str.translate`. Parameters ---------- - table : dict (python 3), str or None (python 2) - In python 3, table is a mapping of Unicode ordinals to Unicode - ordinals, strings, or None. Unmapped characters are left untouched. + table : dict + table is a mapping of Unicode ordinals to Unicode ordinals, strings, or + None. Unmapped characters are left untouched. Characters mapped to None are deleted. :meth:`str.maketrans` is a helper function for making translation tables. - In python 2, table is either a string of length 256 or None. If the - table argument is None, no translation is applied and the operation - simply removes the characters in deletechars. :func:`string.maketrans` - is a helper function for making translation tables. - deletechars : str, optional (python 2) - A string of characters to delete. This argument is only valid - in python 2. Returns ------- Series or Index """ - if deletechars is None: - f = lambda x: x.translate(table) - else: - if compat.PY3: - raise ValueError("deletechars is not a valid argument for " - "str.translate in python 3. You should simply " - "specify character deletions in the table " - "argument") - f = lambda x: x.translate(table, deletechars) - return _na_map(f, arr) + return _na_map(lambda x: x.translate(table), arr) def str_get(arr, i): @@ -2763,8 +2741,8 @@ def get_dummies(self, sep='|'): name=name, expand=True) @copy(str_translate) - def translate(self, table, deletechars=None): - result = str_translate(self._parent, table, deletechars) + def translate(self, table): + result = str_translate(self._parent, table) return self._wrap_result(result) count = _pat_wrapper(str_count, flags=True) diff --git a/pandas/tests/test_strings.py b/pandas/tests/test_strings.py index bdb5066a77d1d..69c76d7a090c4 100644 --- a/pandas/tests/test_strings.py +++ b/pandas/tests/test_strings.py @@ -2161,10 +2161,6 @@ def _check(result, expected): expected = klass(['cdedefg', 'cdee', 'edddfg', 'edefggg']) _check(result, expected) - msg = "deletechars is not a valid argument" - with pytest.raises(ValueError, match=msg): - result = s.str.translate(table, deletechars='fg') - # Series with non-string values s = Series(['a', 'b', 'c', 1.2]) expected = Series(['c', 'd', 'e', np.nan])