diff --git a/doc/source/whatsnew/v0.20.0.txt b/doc/source/whatsnew/v0.20.0.txt index 2a825edd0e98a..65b5952206e36 100644 --- a/doc/source/whatsnew/v0.20.0.txt +++ b/doc/source/whatsnew/v0.20.0.txt @@ -265,6 +265,23 @@ Deprecations - ``DataFrame.astype()`` has deprecated the ``raise_on_error`` parameter in favor of ``errors`` (:issue:`14878`) - ``Series.sortlevel`` and ``DataFrame.sortlevel`` have been deprecated in favor of ``Series.sort_index`` and ``DataFrame.sort_index`` (:issue:`15099`) +.. _whatsnew_0200.moved + +Moved +^^^^^ + +The following exceptions have been relocated from ``pandas.core.common`` to ``pandas.api.exceptions``: + +- ``AbstractMethodError`` +- ``AmbiguousIndexError`` +- ``PandasError`` +- ``PerformanceWarning`` +- ``SettingWithCopyError`` +- ``SettingWithCopyWarning`` +- ``UnsupportedFunctionCall`` +- ``UnsortedIndexError`` + +Raising any of the above exceptions, imported from ``pandas.core.common``, will show a ``DeprecationWarning`` (:issue:`14800`) .. _whatsnew_0200.prior_deprecations: @@ -369,4 +386,4 @@ Bug Fixes - Bug in ``Series`` constructor when both ``copy=True`` and ``dtype`` arguments are provided (:issue:`15125`) - Bug in ``pd.read_csv()`` for the C engine where ``usecols`` were being indexed incorrectly with ``parse_dates`` (:issue:`14792`) -- Bug in ``Series.dt.round`` inconsistent behaviour on NAT's with different arguments (:issue:`14940`) \ No newline at end of file +- Bug in ``Series.dt.round`` inconsistent behaviour on NAT's with different arguments (:issue:`14940`) diff --git a/pandas/api/exceptions.py b/pandas/api/exceptions.py new file mode 100644 index 0000000000000..d3cf9ad419ac3 --- /dev/null +++ b/pandas/api/exceptions.py @@ -0,0 +1,46 @@ + +class PandasError(Exception): + pass + + +class PerformanceWarning(Warning): + pass + + +class SettingWithCopyError(ValueError): + pass + + +class SettingWithCopyWarning(Warning): + pass + + +class AmbiguousIndexError(PandasError, KeyError): + pass + + +class UnsupportedFunctionCall(ValueError): + pass + + +class UnsortedIndexError(KeyError): + """ Error raised when attempting to get a slice of a MultiIndex + and the index has not been lexsorted. Subclass of `KeyError`. + + .. versionadded:: 0.20.0 + + """ + pass + + +class AbstractMethodError(NotImplementedError): + """Raise this error instead of NotImplementedError for abstract methods + while keeping compatibility with Python 2 and Python 3. + """ + + def __init__(self, class_instance): + self.class_instance = class_instance + + def __str__(self): + return ("This method must be defined in the concrete class of %s" % + self.class_instance.__class__.__name__) diff --git a/pandas/api/tests/test_api.py b/pandas/api/tests/test_api.py index b13b4d7de60ca..099e181d9377a 100644 --- a/pandas/api/tests/test_api.py +++ b/pandas/api/tests/test_api.py @@ -3,6 +3,8 @@ import numpy as np import pandas as pd +import pandas.core.common +from pandas.api import exceptions from pandas.core import common as com from pandas import api from pandas.api import types @@ -135,7 +137,7 @@ def test_api(self): class TestApi(Base, tm.TestCase): - allowed = ['tests', 'types'] + allowed = ['exceptions', 'tests', 'types'] def test_api(self): @@ -215,6 +217,50 @@ def test_removed_from_core_common(self): 'ensure_float']: self.assertRaises(AttributeError, lambda: getattr(com, t)) + def test_exceptions_deprecated_in_commom_core(self): + # see issue #14800. Exceptions deprecated & moved from + # pandas.common.core to pandas.api.exceptions + + class _ConcreteClass: + pass + + moved_exceptions = ('AmbiguousIndexError', 'PandasError', + 'PerformanceWarning', 'SettingWithCopyError', + 'SettingWithCopyWarning', + 'UnsupportedFunctionCall', + 'UnsortedIndexError') + + for moved_exception in moved_exceptions: + with tm.assert_produces_warning(DeprecationWarning): + getattr(pandas.core.common, moved_exception)() + + with tm.assert_produces_warning(DeprecationWarning): + pandas.core.common.AbstractMethodError(_ConcreteClass()) + + with self.assertRaises(exceptions.AbstractMethodError): + raise exceptions.AbstractMethodError(_ConcreteClass()) + + with self.assertRaises(exceptions.AmbiguousIndexError): + raise exceptions.AmbiguousIndexError() + + with self.assertRaises(exceptions.PandasError): + raise exceptions.PandasError() + + with self.assertRaises(exceptions.PerformanceWarning): + raise exceptions.PerformanceWarning() + + with self.assertRaises(exceptions.SettingWithCopyError): + raise exceptions.SettingWithCopyError() + + with self.assertRaises(exceptions.SettingWithCopyWarning): + raise exceptions.SettingWithCopyWarning() + + with self.assertRaises(exceptions.UnsupportedFunctionCall): + raise exceptions.UnsupportedFunctionCall() + + with self.assertRaises(exceptions.UnsortedIndexError): + raise exceptions.UnsortedIndexError() + class TestDatetools(tm.TestCase): @@ -228,6 +274,7 @@ def test_deprecation_access_obj(self): check_stacklevel=False): pd.datetools.monthEnd + if __name__ == '__main__': import nose nose.runmodule(argv=[__file__, '-vvs', '-x', '--pdb', '--pdb-failure'], diff --git a/pandas/compat/numpy/function.py b/pandas/compat/numpy/function.py index adc17c7514832..3f78260e82d3c 100644 --- a/pandas/compat/numpy/function.py +++ b/pandas/compat/numpy/function.py @@ -21,7 +21,7 @@ from numpy import ndarray from pandas.util.validators import (validate_args, validate_kwargs, validate_args_and_kwargs) -from pandas.core.common import UnsupportedFunctionCall +from pandas.api.exceptions import UnsupportedFunctionCall from pandas.types.common import is_integer, is_bool from pandas.compat import OrderedDict diff --git a/pandas/core/base.py b/pandas/core/base.py index 77272f7721b32..72267e81f8d9c 100644 --- a/pandas/core/base.py +++ b/pandas/core/base.py @@ -16,7 +16,7 @@ from pandas.compat.numpy import function as nv from pandas.util.decorators import (Appender, cache_readonly, deprecate_kwarg, Substitution) -from pandas.core.common import AbstractMethodError +from pandas.api.exceptions import AbstractMethodError from pandas.formats.printing import pprint_thing _shared_docs = dict() diff --git a/pandas/core/common.py b/pandas/core/common.py index fddac1f29d454..d984ebd9a9594 100644 --- a/pandas/core/common.py +++ b/pandas/core/common.py @@ -20,6 +20,8 @@ from pandas.api import types from pandas.types import common +from pandas.util.depr_module import _add_proxies + # back-compat of public API # deprecate these functions m = sys.modules['pandas.core.common'] @@ -63,6 +65,20 @@ def wrapper(*args, **kwargs): setattr(m, t, outer(t)) +# Relocate exceptions, see #14800 +_moved_exceptions = ('AbstractMethodError', + 'AmbiguousIndexError', + 'PandasError', + 'PerformanceWarning', + 'SettingWithCopyError', + 'SettingWithCopyWarning', + 'UnsupportedFunctionCall', + 'UnsortedIndexError') + +_add_proxies(old_mod_name='pandas.core.common', + new_mod_name='pandas.api.exceptions', + entities=_moved_exceptions) + # deprecate array_equivalent @@ -73,53 +89,6 @@ def array_equivalent(*args, **kwargs): return missing.array_equivalent(*args, **kwargs) -class PandasError(Exception): - pass - - -class PerformanceWarning(Warning): - pass - - -class SettingWithCopyError(ValueError): - pass - - -class SettingWithCopyWarning(Warning): - pass - - -class AmbiguousIndexError(PandasError, KeyError): - pass - - -class UnsupportedFunctionCall(ValueError): - pass - - -class UnsortedIndexError(KeyError): - """ Error raised when attempting to get a slice of a MultiIndex - and the index has not been lexsorted. Subclass of `KeyError`. - - .. versionadded:: 0.20.0 - - """ - pass - - -class AbstractMethodError(NotImplementedError): - """Raise this error instead of NotImplementedError for abstract methods - while keeping compatibility with Python 2 and Python 3. - """ - - def __init__(self, class_instance): - self.class_instance = class_instance - - def __str__(self): - return ("This method must be defined in the concrete class of %s" % - self.class_instance.__class__.__name__) - - def flatten(l): """Flatten an arbitrarily nested sequence. diff --git a/pandas/core/frame.py b/pandas/core/frame.py index 4288e03c2cc49..e8308e043192e 100644 --- a/pandas/core/frame.py +++ b/pandas/core/frame.py @@ -56,7 +56,9 @@ is_named_tuple) from pandas.types.missing import isnull, notnull -from pandas.core.common import (PandasError, _try_sort, +from pandas.api.exceptions import PandasError + +from pandas.core.common import (_try_sort, _default_index, _values_from_object, _maybe_box_datetimelike, diff --git a/pandas/core/generic.py b/pandas/core/generic.py index 0b5767da74cad..88c6489c5f8a9 100644 --- a/pandas/core/generic.py +++ b/pandas/core/generic.py @@ -27,11 +27,11 @@ from pandas.types.cast import _maybe_promote, _maybe_upcast_putmask from pandas.types.missing import isnull, notnull from pandas.types.generic import ABCSeries, ABCPanel - +from pandas.api.exceptions import SettingWithCopyError, AbstractMethodError from pandas.core.common import (_values_from_object, - _maybe_box_datetimelike, - SettingWithCopyError, SettingWithCopyWarning, - AbstractMethodError) + _maybe_box_datetimelike) + +from pandas.api.exceptions import SettingWithCopyWarning from pandas.core.base import PandasObject from pandas.core.index import (Index, MultiIndex, _ensure_index, diff --git a/pandas/core/groupby.py b/pandas/core/groupby.py index 700e279cb0030..1d5a8a84e011c 100644 --- a/pandas/core/groupby.py +++ b/pandas/core/groupby.py @@ -32,8 +32,8 @@ _ensure_float) from pandas.types.cast import _possibly_downcast_to_dtype from pandas.types.missing import isnull, notnull, _maybe_fill - -from pandas.core.common import _values_from_object, AbstractMethodError +from pandas.api.exceptions import AbstractMethodError +from pandas.core.common import _values_from_object from pandas.core.base import (PandasObject, SelectionMixin, GroupByError, DataError, SpecificationError) from pandas.core.categorical import Categorical diff --git a/pandas/core/ops.py b/pandas/core/ops.py index 396b0e048bc49..df0e9d38f8cec 100644 --- a/pandas/core/ops.py +++ b/pandas/core/ops.py @@ -19,8 +19,8 @@ from pandas.compat import bind_method import pandas.core.missing as missing import pandas.algos as _algos -from pandas.core.common import (_values_from_object, _maybe_match_name, - PerformanceWarning) +from pandas.api.exceptions import PerformanceWarning +from pandas.core.common import _values_from_object, _maybe_match_name from pandas.types.missing import notnull, isnull from pandas.types.common import (needs_i8_conversion, is_datetimelike_v_numeric, diff --git a/pandas/core/panel.py b/pandas/core/panel.py index f708774dd84ff..b4fc13a86ca90 100644 --- a/pandas/core/panel.py +++ b/pandas/core/panel.py @@ -14,6 +14,8 @@ is_string_like, is_scalar) from pandas.types.missing import notnull +from pandas.api.exceptions import PandasError + import pandas.computation.expressions as expressions import pandas.core.common as com import pandas.core.ops as ops @@ -21,7 +23,7 @@ from pandas import compat from pandas.compat import (map, zip, range, u, OrderedDict, OrderedDefaultdict) from pandas.compat.numpy import function as nv -from pandas.core.common import PandasError, _try_sort, _default_index +from pandas.core.common import _try_sort, _default_index from pandas.core.frame import DataFrame from pandas.core.generic import NDFrame, _shared_docs from pandas.core.index import (Index, MultiIndex, _ensure_index, diff --git a/pandas/core/series.py b/pandas/core/series.py index d967e2d02d41f..2bc48d36ced36 100644 --- a/pandas/core/series.py +++ b/pandas/core/series.py @@ -32,14 +32,13 @@ _possibly_convert_platform, _possibly_cast_to_datetime, _possibly_castable) from pandas.types.missing import isnull, notnull - +from pandas.api.exceptions import SettingWithCopyError from pandas.core.common import (is_bool_indexer, _default_index, _asarray_tuplesafe, _values_from_object, _try_sort, _maybe_match_name, - SettingWithCopyError, _maybe_box_datetimelike, _dict_compat) from pandas.core.index import (Index, MultiIndex, InvalidIndexError, diff --git a/pandas/indexes/multi.py b/pandas/indexes/multi.py index 2afafaeb544d1..c8f7249939b42 100644 --- a/pandas/indexes/multi.py +++ b/pandas/indexes/multi.py @@ -22,11 +22,10 @@ is_list_like, is_scalar) from pandas.types.missing import isnull, array_equivalent +from pandas.api.exceptions import PerformanceWarning, UnsortedIndexError from pandas.core.common import (_values_from_object, is_bool_indexer, - is_null_slice, - PerformanceWarning, - UnsortedIndexError) + is_null_slice) from pandas.core.base import FrozenList diff --git a/pandas/io/common.py b/pandas/io/common.py index 6817c824ad786..2e2dad216dbf3 100644 --- a/pandas/io/common.py +++ b/pandas/io/common.py @@ -9,7 +9,7 @@ from pandas.compat import StringIO, BytesIO, string_types, text_type from pandas import compat from pandas.formats.printing import pprint_thing -from pandas.core.common import AbstractMethodError +from pandas.api.exceptions import AbstractMethodError from pandas.types.common import is_number try: diff --git a/pandas/io/gbq.py b/pandas/io/gbq.py index 966f53e9d75ef..a3a40b751c6f0 100644 --- a/pandas/io/gbq.py +++ b/pandas/io/gbq.py @@ -13,7 +13,7 @@ from pandas import compat from pandas.core.api import DataFrame from pandas.tools.merge import concat -from pandas.core.common import PandasError +from pandas.api.exceptions import PandasError from pandas.compat import lzip, bytes_to_str diff --git a/pandas/io/html.py b/pandas/io/html.py index 3c38dae91eb89..141704d1dde35 100644 --- a/pandas/io/html.py +++ b/pandas/io/html.py @@ -19,7 +19,7 @@ from pandas.compat import (lrange, lmap, u, string_types, iteritems, raise_with_traceback, binary_type) from pandas import Series -from pandas.core.common import AbstractMethodError +from pandas.api.exceptions import AbstractMethodError from pandas.formats.printing import pprint_thing _IMPORTS = False diff --git a/pandas/io/json.py b/pandas/io/json.py index 0a6b8af179e12..716137133f9ca 100644 --- a/pandas/io/json.py +++ b/pandas/io/json.py @@ -10,8 +10,8 @@ from pandas.compat import StringIO, long, u from pandas import compat, isnull from pandas import Series, DataFrame, to_datetime +from pandas.api.exceptions import AbstractMethodError from pandas.io.common import get_filepath_or_buffer, _get_handle -from pandas.core.common import AbstractMethodError from pandas.formats.printing import pprint_thing loads = _json.loads diff --git a/pandas/io/packers.py b/pandas/io/packers.py index ab44e46c96b77..70ba089aeeb7e 100644 --- a/pandas/io/packers.py +++ b/pandas/io/packers.py @@ -59,7 +59,7 @@ from pandas.sparse.api import SparseSeries, SparseDataFrame from pandas.sparse.array import BlockIndex, IntIndex from pandas.core.generic import NDFrame -from pandas.core.common import PerformanceWarning +from pandas.api.exceptions import PerformanceWarning from pandas.io.common import get_filepath_or_buffer from pandas.core.internals import BlockManager, make_block, _safe_reshape import pandas.core.internals as internals diff --git a/pandas/io/parsers.py b/pandas/io/parsers.py index fdf26fdef6b25..e3d0ce095dff0 100755 --- a/pandas/io/parsers.py +++ b/pandas/io/parsers.py @@ -22,11 +22,11 @@ is_scalar, is_categorical_dtype) from pandas.types.missing import isnull from pandas.types.cast import _astype_nansafe +from pandas.api.exceptions import AbstractMethodError from pandas.core.index import Index, MultiIndex, RangeIndex from pandas.core.series import Series from pandas.core.frame import DataFrame from pandas.core.categorical import Categorical -from pandas.core.common import AbstractMethodError from pandas.io.date_converters import generic_parser from pandas.io.common import (get_filepath_or_buffer, _validate_header_arg, _get_handle, UnicodeReader, UTF8Recoder, diff --git a/pandas/io/pytables.py b/pandas/io/pytables.py index e474aeab1f6ca..e37761e485bfb 100644 --- a/pandas/io/pytables.py +++ b/pandas/io/pytables.py @@ -35,7 +35,8 @@ from pandas.tseries.tdi import TimedeltaIndex from pandas.core.base import StringMixin from pandas.formats.printing import adjoin, pprint_thing -from pandas.core.common import _asarray_tuplesafe, PerformanceWarning +from pandas.api.exceptions import PerformanceWarning +from pandas.core.common import _asarray_tuplesafe from pandas.core.algorithms import match, unique from pandas.core.categorical import Categorical, _factorize_from_iterables from pandas.core.internals import (BlockManager, make_block, diff --git a/pandas/io/tests/parser/test_parsers.py b/pandas/io/tests/parser/test_parsers.py index a90f546d37fc8..733bd1a841290 100644 --- a/pandas/io/tests/parser/test_parsers.py +++ b/pandas/io/tests/parser/test_parsers.py @@ -6,7 +6,7 @@ import pandas.util.testing as tm from pandas import read_csv, read_table -from pandas.core.common import AbstractMethodError +from pandas.api.exceptions import AbstractMethodError from .common import ParserTests from .header import HeaderTests diff --git a/pandas/io/tests/test_packers.py b/pandas/io/tests/test_packers.py index 63c2ffc629ca6..219ac044f02fd 100644 --- a/pandas/io/tests/test_packers.py +++ b/pandas/io/tests/test_packers.py @@ -10,7 +10,7 @@ from pandas.compat import u, PY3 from pandas import (Series, DataFrame, Panel, MultiIndex, bdate_range, date_range, period_range, Index, Categorical) -from pandas.core.common import PerformanceWarning +from pandas.api.exceptions import PerformanceWarning from pandas.io.packers import to_msgpack, read_msgpack import pandas.util.testing as tm from pandas.util.testing import (ensure_clean, diff --git a/pandas/tests/formats/test_format.py b/pandas/tests/formats/test_format.py index 00e5e002ca48d..27ed7098492b9 100644 --- a/pandas/tests/formats/test_format.py +++ b/pandas/tests/formats/test_format.py @@ -36,7 +36,6 @@ import pandas.formats.format as fmt import pandas.util.testing as tm -import pandas.core.common as com import pandas.formats.printing as printing from pandas.util.terminal import get_terminal_size import pandas as pd diff --git a/pandas/tests/frame/test_axis_select_reindex.py b/pandas/tests/frame/test_axis_select_reindex.py index ecce17f96a672..2668d48fc5d30 100644 --- a/pandas/tests/frame/test_axis_select_reindex.py +++ b/pandas/tests/frame/test_axis_select_reindex.py @@ -16,7 +16,7 @@ assert_frame_equal, assertRaisesRegexp) -from pandas.core.common import PerformanceWarning +from pandas.api.exceptions import PerformanceWarning import pandas.util.testing as tm from pandas.tests.frame.common import TestData diff --git a/pandas/tests/frame/test_constructors.py b/pandas/tests/frame/test_constructors.py index bf0fabaf3e402..36bed779f9ae6 100644 --- a/pandas/tests/frame/test_constructors.py +++ b/pandas/tests/frame/test_constructors.py @@ -21,9 +21,9 @@ from pandas import (DataFrame, Index, Series, isnull, MultiIndex, Timedelta, Timestamp, date_range) -from pandas.core.common import PandasError +from pandas.api.exceptions import PandasError import pandas as pd -import pandas.core.common as com +import pandas.api.exceptions as excp import pandas.lib as lib import pandas.util.testing as tm @@ -1245,8 +1245,8 @@ def test_constructor_single_value(self): dtype=object), index=[1, 2], columns=['a', 'c'])) - self.assertRaises(com.PandasError, DataFrame, 'a', [1, 2]) - self.assertRaises(com.PandasError, DataFrame, 'a', columns=['a', 'c']) + self.assertRaises(excp.PandasError, DataFrame, 'a', [1, 2]) + self.assertRaises(excp.PandasError, DataFrame, 'a', columns=['a', 'c']) with tm.assertRaisesRegexp(TypeError, 'incompatible data and dtype'): DataFrame('a', [1, 2], ['a', 'c'], float) diff --git a/pandas/tests/frame/test_indexing.py b/pandas/tests/frame/test_indexing.py index abe40f7be1d90..b51a5a52492c6 100644 --- a/pandas/tests/frame/test_indexing.py +++ b/pandas/tests/frame/test_indexing.py @@ -11,7 +11,7 @@ from numpy.random import randn import numpy as np -import pandas.core.common as com +import pandas.api.exceptions as excp from pandas import (DataFrame, Index, Series, notnull, isnull, MultiIndex, DatetimeIndex, Timestamp, date_range) @@ -446,7 +446,7 @@ def test_setitem(self): def f(): smaller['col10'] = ['1', '2'] - self.assertRaises(com.SettingWithCopyError, f) + self.assertRaises(excp.SettingWithCopyError, f) self.assertEqual(smaller['col10'].dtype, np.object_) self.assertTrue((smaller['col10'] == ['1', '2']).all()) @@ -913,7 +913,7 @@ def test_fancy_getitem_slice_mixed(self): def f(): sliced['C'] = 4. - self.assertRaises(com.SettingWithCopyError, f) + self.assertRaises(excp.SettingWithCopyError, f) self.assertTrue((self.frame['C'] == 4).all()) def test_fancy_setitem_int_labels(self): @@ -1714,7 +1714,7 @@ def test_irow(self): # setting it makes it raise/warn def f(): result[2] = 0. - self.assertRaises(com.SettingWithCopyError, f) + self.assertRaises(excp.SettingWithCopyError, f) exp_col = df[2].copy() exp_col[4:8] = 0. assert_series_equal(df[2], exp_col) @@ -1749,7 +1749,7 @@ def test_icol(self): # and that we are setting a copy def f(): result[8] = 0. - self.assertRaises(com.SettingWithCopyError, f) + self.assertRaises(excp.SettingWithCopyError, f) self.assertTrue((df[8] == 0).all()) # list of integers diff --git a/pandas/tests/groupby/test_groupby.py b/pandas/tests/groupby/test_groupby.py index 873c63ca257c4..79b19614602dc 100644 --- a/pandas/tests/groupby/test_groupby.py +++ b/pandas/tests/groupby/test_groupby.py @@ -7,9 +7,9 @@ from pandas.types.common import _ensure_platform_int from pandas import date_range, bdate_range, Timestamp, isnull +from pandas.api.exceptions import UnsupportedFunctionCall from pandas.core.index import Index, MultiIndex, CategoricalIndex from pandas.core.api import Categorical, DataFrame -from pandas.core.common import UnsupportedFunctionCall from pandas.core.groupby import (SpecificationError, DataError, _nargsort, _lexsort_indexer) from pandas.core.series import Series @@ -24,6 +24,7 @@ from pandas.tools.merge import concat from collections import defaultdict from functools import partial +import pandas.api.exceptions as excp import pandas.core.common as com import numpy as np @@ -4319,7 +4320,7 @@ def test_groupby_multiindex_not_lexsorted(self): tm.assert_frame_equal(lexsorted_df, not_lexsorted_df) expected = lexsorted_df.groupby('a').mean() - with tm.assert_produces_warning(com.PerformanceWarning): + with tm.assert_produces_warning(excp.PerformanceWarning): result = not_lexsorted_df.groupby('a').mean() tm.assert_frame_equal(expected, result) diff --git a/pandas/tests/indexes/test_multi.py b/pandas/tests/indexes/test_multi.py index 2861a1f56b24b..b9fcaf5510e63 100644 --- a/pandas/tests/indexes/test_multi.py +++ b/pandas/tests/indexes/test_multi.py @@ -15,7 +15,7 @@ from pandas import (CategoricalIndex, DataFrame, Index, MultiIndex, compat, date_range, period_range) from pandas.compat import PY3, long, lrange, lzip, range, u -from pandas.core.common import PerformanceWarning, UnsortedIndexError +from pandas.api.exceptions import PerformanceWarning, UnsortedIndexError from pandas.indexes.base import InvalidIndexError from pandas.lib import Timestamp diff --git a/pandas/tests/indexing/test_indexing.py b/pandas/tests/indexing/test_indexing.py index 6fc24e41ee914..7c0490c31efd2 100644 --- a/pandas/tests/indexing/test_indexing.py +++ b/pandas/tests/indexing/test_indexing.py @@ -16,14 +16,14 @@ import numpy as np import pandas as pd -import pandas.core.common as com +import pandas.api.exceptions as excp from pandas import option_context from pandas.core.indexing import _non_reducing_slice, _maybe_numeric_slice from pandas.core.api import (DataFrame, Index, Series, Panel, isnull, MultiIndex, Timestamp, Timedelta) from pandas.formats.printing import pprint_thing from pandas import concat -from pandas.core.common import PerformanceWarning, UnsortedIndexError +from pandas.api.exceptions import PerformanceWarning, UnsortedIndexError import pandas.util.testing as tm from pandas import date_range @@ -4636,12 +4636,12 @@ def test_detect_chained_assignment(self): def f(): df['A'][0] = -5 - self.assertRaises(com.SettingWithCopyError, f) + self.assertRaises(excp.SettingWithCopyError, f) def f(): df['A'][1] = np.nan - self.assertRaises(com.SettingWithCopyError, f) + self.assertRaises(excp.SettingWithCopyError, f) self.assertIsNone(df['A'].is_copy) # using a copy (the chain), fails @@ -4651,7 +4651,7 @@ def f(): def f(): df.loc[0]['A'] = -5 - self.assertRaises(com.SettingWithCopyError, f) + self.assertRaises(excp.SettingWithCopyError, f) # doc example df = DataFrame({'a': ['one', 'one', 'two', 'three', @@ -4666,7 +4666,7 @@ def f(): indexer = df.a.str.startswith('o') df[indexer]['c'] = 42 - self.assertRaises(com.SettingWithCopyError, f) + self.assertRaises(excp.SettingWithCopyError, f) expected = DataFrame({'A': [111, 'bbb', 'ccc'], 'B': [1, 2, 3]}) df = DataFrame({'A': ['aaa', 'bbb', 'ccc'], 'B': [1, 2, 3]}) @@ -4674,12 +4674,12 @@ def f(): def f(): df['A'][0] = 111 - self.assertRaises(com.SettingWithCopyError, f) + self.assertRaises(excp.SettingWithCopyError, f) def f(): df.loc[0]['A'] = 111 - self.assertRaises(com.SettingWithCopyError, f) + self.assertRaises(excp.SettingWithCopyError, f) df.loc[0, 'A'] = 111 tm.assert_frame_equal(df, expected) @@ -4768,7 +4768,7 @@ def random_text(nobs=100): def f(): zed['eyes']['right'].fillna(value=555, inplace=True) - self.assertRaises(com.SettingWithCopyError, f) + self.assertRaises(excp.SettingWithCopyError, f) df = DataFrame(np.random.randn(10, 4)) s = df.iloc[:, 0].sort_values() @@ -4793,7 +4793,7 @@ def f(): def f(): df.iloc[0:5]['group'] = 'a' - self.assertRaises(com.SettingWithCopyError, f) + self.assertRaises(excp.SettingWithCopyError, f) # mixed type setting # same dtype & changing dtype @@ -4805,17 +4805,17 @@ def f(): def f(): df.ix[2]['D'] = 'foo' - self.assertRaises(com.SettingWithCopyError, f) + self.assertRaises(excp.SettingWithCopyError, f) def f(): df.ix[2]['C'] = 'foo' - self.assertRaises(com.SettingWithCopyError, f) + self.assertRaises(excp.SettingWithCopyError, f) def f(): df['C'][2] = 'foo' - self.assertRaises(com.SettingWithCopyError, f) + self.assertRaises(excp.SettingWithCopyError, f) def test_setting_with_copy_bug(self): @@ -4828,7 +4828,7 @@ def test_setting_with_copy_bug(self): def f(): df[['c']][mask] = df[['b']][mask] - self.assertRaises(com.SettingWithCopyError, f) + self.assertRaises(excp.SettingWithCopyError, f) # invalid warning as we are returning a new object # GH 8730 @@ -4845,7 +4845,7 @@ def test_detect_chained_assignment_warnings(self): with option_context('chained_assignment', 'warn'): df = DataFrame({'A': ['aaa', 'bbb', 'ccc'], 'B': [1, 2, 3]}) with tm.assert_produces_warning( - expected_warning=com.SettingWithCopyWarning): + expected_warning=excp.SettingWithCopyWarning): df.loc[0]['A'] = 111 def test_float64index_slicing_bug(self): diff --git a/pandas/tests/series/test_datetime_values.py b/pandas/tests/series/test_datetime_values.py index b9f999a6c6ffe..ea7d97785227d 100644 --- a/pandas/tests/series/test_datetime_values.py +++ b/pandas/tests/series/test_datetime_values.py @@ -12,7 +12,7 @@ from pandas.tseries.period import PeriodIndex from pandas.tseries.index import Timestamp, DatetimeIndex from pandas.tseries.tdi import TimedeltaIndex -import pandas.core.common as com +import pandas.api.exceptions as excp from pandas.util.testing import assert_series_equal import pandas.util.testing as tm @@ -270,7 +270,7 @@ def get_dir(s): def f(): s.dt.hour[0] = 5 - self.assertRaises(com.SettingWithCopyError, f) + self.assertRaises(excp.SettingWithCopyError, f) def test_dt_accessor_no_new_attributes(self): # https://github.com/pandas-dev/pandas/issues/10673 diff --git a/pandas/tests/test_multilevel.py b/pandas/tests/test_multilevel.py index 59d9e1e094d9d..15ec56d85f2e5 100755 --- a/pandas/tests/test_multilevel.py +++ b/pandas/tests/test_multilevel.py @@ -13,7 +13,7 @@ from pandas.types.common import is_float_dtype, is_integer_dtype from pandas.util.testing import (assert_almost_equal, assert_series_equal, assert_frame_equal, assertRaisesRegexp) -import pandas.core.common as com +import pandas.api.exceptions as excp import pandas.util.testing as tm from pandas.compat import (range, lrange, StringIO, lzip, u, product as cart_product, zip) @@ -544,7 +544,7 @@ def test_xs_level(self): def f(x): x[:] = 10 - self.assertRaises(com.SettingWithCopyError, f, result) + self.assertRaises(excp.SettingWithCopyError, f, result) def test_xs_level_multiple(self): from pandas import read_table @@ -568,7 +568,7 @@ def test_xs_level_multiple(self): def f(x): x[:] = 10 - self.assertRaises(com.SettingWithCopyError, f, result) + self.assertRaises(excp.SettingWithCopyError, f, result) # GH2107 dates = lrange(20111201, 20111205) @@ -1428,7 +1428,7 @@ def f(): df['foo']['one'] = 2 return df - self.assertRaises(com.SettingWithCopyError, f) + self.assertRaises(excp.SettingWithCopyError, f) try: df = f() diff --git a/pandas/tests/test_window.py b/pandas/tests/test_window.py index 929ff43bfaaad..3f2ee10370670 100644 --- a/pandas/tests/test_window.py +++ b/pandas/tests/test_window.py @@ -16,7 +16,7 @@ import pandas.core.window as rwindow import pandas.tseries.offsets as offsets from pandas.core.base import SpecificationError -from pandas.core.common import UnsupportedFunctionCall +from pandas.api.exceptions import UnsupportedFunctionCall import pandas.util.testing as tm from pandas.compat import range, zip, PY3 diff --git a/pandas/tools/plotting.py b/pandas/tools/plotting.py index bd9933b12b580..e3d6b33961614 100644 --- a/pandas/tools/plotting.py +++ b/pandas/tools/plotting.py @@ -20,8 +20,8 @@ from pandas.util.decorators import cache_readonly, deprecate_kwarg from pandas.core.base import PandasObject - -from pandas.core.common import AbstractMethodError, _try_sort +from pandas.api.exceptions import AbstractMethodError +from pandas.core.common import _try_sort from pandas.core.generic import _shared_docs, _shared_doc_kwargs from pandas.core.index import Index, MultiIndex from pandas.core.series import Series, remove_na diff --git a/pandas/tseries/base.py b/pandas/tseries/base.py index a8dd2238c2063..ffffa032b5b38 100644 --- a/pandas/tseries/base.py +++ b/pandas/tseries/base.py @@ -17,7 +17,7 @@ from pandas.types.missing import isnull from pandas.core import common as com, algorithms from pandas.core.algorithms import checked_add_with_arr -from pandas.core.common import AbstractMethodError +from pandas.api.exceptions import AbstractMethodError import pandas.formats.printing as printing import pandas.tslib as tslib diff --git a/pandas/tseries/index.py b/pandas/tseries/index.py index aca962c8178d3..9e6ff1fe8145a 100644 --- a/pandas/tseries/index.py +++ b/pandas/tseries/index.py @@ -25,8 +25,8 @@ from pandas.types.missing import isnull import pandas.types.concat as _concat -from pandas.core.common import (_values_from_object, _maybe_box, - PerformanceWarning) +from pandas.api.exceptions import PerformanceWarning +from pandas.core.common import _values_from_object, _maybe_box from pandas.core.index import Index, Int64Index, Float64Index from pandas.indexes.base import _index_shared_docs diff --git a/pandas/tseries/offsets.py b/pandas/tseries/offsets.py index 370dd00762896..e467ab84fb1d6 100644 --- a/pandas/tseries/offsets.py +++ b/pandas/tseries/offsets.py @@ -5,7 +5,7 @@ from pandas.types.generic import ABCSeries, ABCDatetimeIndex, ABCPeriod from pandas.tseries.tools import to_datetime, normalize_date -from pandas.core.common import AbstractMethodError +from pandas.api.exceptions import AbstractMethodError # import after tools, dateutil check from dateutil.relativedelta import relativedelta, weekday diff --git a/pandas/tseries/resample.py b/pandas/tseries/resample.py index e6d500144fa44..723bce1ebc17a 100755 --- a/pandas/tseries/resample.py +++ b/pandas/tseries/resample.py @@ -14,6 +14,7 @@ from pandas.tseries.tdi import TimedeltaIndex from pandas.tseries.offsets import DateOffset, Tick, Day, _delta_to_nanoseconds from pandas.tseries.period import PeriodIndex, period_range +import pandas.api.exceptions as excp import pandas.core.common as com import pandas.core.algorithms as algos @@ -197,7 +198,7 @@ def __setattr__(self, attr, value): def __getitem__(self, key): try: return super(Resampler, self).__getitem__(key) - except (KeyError, com.AbstractMethodError): + except (KeyError, excp.AbstractMethodError): # compat for deprecated if isinstance(self.obj, com.ABCSeries): diff --git a/pandas/tseries/tests/test_daterange.py b/pandas/tseries/tests/test_daterange.py index 87f9f55e0189c..f915e3864c990 100644 --- a/pandas/tseries/tests/test_daterange.py +++ b/pandas/tseries/tests/test_daterange.py @@ -11,7 +11,7 @@ generate_range, DateOffset, Minute) from pandas.tseries.index import cdate_range, bdate_range, date_range -from pandas.core import common as com +from pandas.api import exceptions from pandas.util.testing import assertRaisesRegexp import pandas.util.testing as tm @@ -669,7 +669,7 @@ def test_shift(self): self.assertEqual(shifted[0], self.rng[0]) self.assertEqual(shifted.offset, self.rng.offset) - with tm.assert_produces_warning(com.PerformanceWarning): + with tm.assert_produces_warning(exceptions.PerformanceWarning): rng = date_range(START, END, freq=BMonthEnd()) shifted = rng.shift(1, freq=CDay()) self.assertEqual(shifted[0], rng[0] + CDay()) diff --git a/pandas/tseries/tests/test_resample.py b/pandas/tseries/tests/test_resample.py index 26c311b4a72f8..39e755cd2d230 100755 --- a/pandas/tseries/tests/test_resample.py +++ b/pandas/tseries/tests/test_resample.py @@ -15,7 +15,7 @@ from pandas.types.generic import ABCSeries, ABCDataFrame from pandas.compat import range, lrange, zip, product, OrderedDict from pandas.core.base import SpecificationError -from pandas.core.common import UnsupportedFunctionCall +from pandas.api.exceptions import UnsupportedFunctionCall from pandas.core.groupby import DataError from pandas.tseries.frequencies import MONTHS, DAYS from pandas.tseries.frequencies import to_offset diff --git a/pandas/tseries/tests/test_timeseries.py b/pandas/tseries/tests/test_timeseries.py index 58a4457777ea0..231cff8568f32 100644 --- a/pandas/tseries/tests/test_timeseries.py +++ b/pandas/tseries/tests/test_timeseries.py @@ -26,7 +26,7 @@ NaT, timedelta_range, Timedelta, _np_version_under1p8, concat) from pandas.compat import range, long, StringIO, lrange, lmap, zip, product from pandas.compat.numpy import np_datetime64_compat -from pandas.core.common import PerformanceWarning +from pandas.api.exceptions import PerformanceWarning from pandas.tslib import iNaT from pandas.util.testing import ( assert_frame_equal, assert_series_equal, assert_almost_equal, diff --git a/pandas/util/depr_module.py b/pandas/util/depr_module.py index 736d2cdaab31c..26ba2ca1340ec 100644 --- a/pandas/util/depr_module.py +++ b/pandas/util/depr_module.py @@ -1,8 +1,9 @@ """ -This module houses a utility class for mocking deprecated modules. -It is for internal use only and should not be used beyond this purpose. +This module houses utilities mocking deprecated enties. +They are for internal use only and should not be used beyond this purpose. """ +import sys import warnings import importlib @@ -62,3 +63,44 @@ def _import_deprmod(self): warnings.filterwarnings('ignore', category=FutureWarning) deprmodule = importlib.import_module(self.deprmod) return deprmodule + + +def _add_proxies(old_mod_name, new_mod_name, entities): + """ Mock entities moved between modules + + Parameters + ---------- + old_mod_name : module that used to contain the entity implementation + new_mod_name : module contains the implementations of the entities + entities : iterable of the names of the mocked entities + + The mechanics are as follows: + + 1. Physically move the entity from 'old_mod_name' to 'new_mod_name' + 2. Add the name of the above entity to the 'entities' iterable + 3. Repeat the (1-2) for each entity you want to move + + Invoking the moved entity from 'old_mod_name' will act as proxy to the + actual entity in 'new_mod_name'. If warnings are enabled a deprecation + warning will be issued. + """ + + def create_proxy(entity): + + def wrapper(*args, **kwargs): + warnings.warn("{old}.{entity} has been deprecated. Use " + "{new}.{entity} instead.".format(entity=entity, + old=old_mod_name, + new=new_mod_name), + DeprecationWarning, stacklevel=2) + + return getattr(new_mod, entity)(*args, **kwargs) + + return wrapper + + importlib.import_module(new_mod_name) + old_mod = sys.modules[old_mod_name] + new_mod = sys.modules[new_mod_name] + + for entity in entities: + setattr(old_mod, entity, create_proxy(entity))