Skip to content

ENH: Move SettingWithCopyWarning to error/__init__.py per GH27656 #47198

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions doc/source/reference/testing.rst
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ Exceptions and warnings
errors.ParserWarning
errors.PerformanceWarning
errors.SettingWithCopyError
errors.SettingWithCopyWarning
errors.SpecificationError
errors.UnsortedIndexError
errors.UnsupportedFunctionCall
Expand Down
2 changes: 1 addition & 1 deletion doc/source/whatsnew/v1.5.0.rst
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,7 @@ Other enhancements
- A :class:`errors.PerformanceWarning` is now thrown when using ``string[pyarrow]`` dtype with methods that don't dispatch to ``pyarrow.compute`` methods (:issue:`42613`)
- Added ``numeric_only`` argument to :meth:`Resampler.sum`, :meth:`Resampler.prod`, :meth:`Resampler.min`, :meth:`Resampler.max`, :meth:`Resampler.first`, and :meth:`Resampler.last` (:issue:`46442`)
- ``times`` argument in :class:`.ExponentialMovingWindow` now accepts ``np.timedelta64`` (:issue:`47003`)
- :class:`DataError`, :class:`SpecificationError`, and :class:`SettingWithCopyError` are now exposed in ``pandas.errors`` (:issue:`27656`)
- :class:`DataError`, :class:`SpecificationError`, :class:`SettingWithCopyError`, and :class:`SettingWithCopyWarning` are now exposed in ``pandas.errors`` (:issue:`27656`)

.. ---------------------------------------------------------------------------
.. _whatsnew_150.notable_bug_fixes:
Expand Down
4 changes: 0 additions & 4 deletions pandas/core/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,10 +58,6 @@
from pandas import Index


class SettingWithCopyWarning(Warning):
pass


def flatten(line):
"""
Flatten an arbitrarily nested sequence.
Expand Down
3 changes: 2 additions & 1 deletion pandas/core/generic.py
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@
AbstractMethodError,
InvalidIndexError,
SettingWithCopyError,
SettingWithCopyWarning,
)
from pandas.util._decorators import (
deprecate_kwarg,
Expand Down Expand Up @@ -3952,7 +3953,7 @@ def _check_setitem_copy(self, t="setting", force=False):
if value == "raise":
raise SettingWithCopyError(t)
elif value == "warn":
warnings.warn(t, com.SettingWithCopyWarning, stacklevel=find_stack_level())
warnings.warn(t, SettingWithCopyWarning, stacklevel=find_stack_level())

def __delitem__(self, key) -> None:
"""
Expand Down
28 changes: 24 additions & 4 deletions pandas/errors/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -275,11 +275,11 @@ class SettingWithCopyError(ValueError):
the mode.chained_assignment is set to 'raise.' This can happen unintentionally
when chained indexing.

For more information, see 'Evaluation order matters' on
https://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html
For more information on eveluation order,
see :ref:`the user guide<indexing.evaluation_order>`.

For more information, see 'Indexing view versus copy' on
https://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html
For more information on view vs. copy,
see :ref:`the user guide<indexing.view_versus_copy>`.

Examples
--------
Expand All @@ -288,3 +288,23 @@ class SettingWithCopyError(ValueError):
>>> df.loc[0:3]['A'] = 'a' # doctest: +SKIP
... # SettingWithCopyError: A value is trying to be set on a copy of a...
"""


class SettingWithCopyWarning(Warning):
"""
Warning is raised when trying to set on a copied slice from a dataframe and
the mode.chained_assignment is set to 'warn.' 'Warn' is the default option.
This can happen unintentionally when chained indexing.

For more information on eveluation order,
see :ref:`the user guide<indexing.evaluation_order>`.

For more information on view vs. copy,
see :ref:`the user guide<indexing.view_versus_copy>`.

Examples
--------
>>> df = pd.DataFrame({'A': [1, 1, 1, 2, 2]}, columns=['A'])
>>> df.loc[0:3]['A'] = 'a' # doctest: +SKIP
... # SettingWithCopyWarning: A value is trying to be set on a copy of a...
"""
27 changes: 14 additions & 13 deletions pandas/tests/copy_view/test_indexing.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
import numpy as np
import pytest

from pandas.errors import SettingWithCopyWarning

import pandas as pd
from pandas import (
DataFrame,
Series,
)
import pandas._testing as tm
import pandas.core.common as com
from pandas.tests.copy_view.util import get_array

# -----------------------------------------------------------------------------
Expand All @@ -31,7 +32,7 @@ def test_subset_column_selection(using_copy_on_write):
assert not np.shares_memory(get_array(subset, "a"), get_array(df, "a"))
# INFO this no longer raise warning since pandas 1.4
# with pd.option_context("chained_assignment", "warn"):
# with tm.assert_produces_warning(com.SettingWithCopyWarning):
# with tm.assert_produces_warning(SettingWithCopyWarning):
subset.iloc[0, 0] = 0

assert not np.shares_memory(get_array(subset, "a"), get_array(df, "a"))
Expand Down Expand Up @@ -80,7 +81,7 @@ def test_subset_row_slice(using_copy_on_write):
else:
# INFO this no longer raise warning since pandas 1.4
# with pd.option_context("chained_assignment", "warn"):
# with tm.assert_produces_warning(com.SettingWithCopyWarning):
# with tm.assert_produces_warning(SettingWithCopyWarning):
subset.iloc[0, 0] = 0

subset._mgr._verify_integrity()
Expand Down Expand Up @@ -119,7 +120,7 @@ def test_subset_column_slice(using_copy_on_write, using_array_manager, dtype):

else:
# we only get a warning in case of a single block
warn = com.SettingWithCopyWarning if single_block else None
warn = SettingWithCopyWarning if single_block else None
with pd.option_context("chained_assignment", "warn"):
with tm.assert_produces_warning(warn):
subset.iloc[0, 0] = 0
Expand Down Expand Up @@ -252,7 +253,7 @@ def test_subset_set_with_row_indexer(indexer_si, indexer, using_copy_on_write):
indexer_si(subset)[indexer] = 0
else:
# INFO iloc no longer raises warning since pandas 1.4
warn = com.SettingWithCopyWarning if indexer_si is tm.setitem else None
warn = SettingWithCopyWarning if indexer_si is tm.setitem else None
with pd.option_context("chained_assignment", "warn"):
with tm.assert_produces_warning(warn):
indexer_si(subset)[indexer] = 0
Expand Down Expand Up @@ -282,7 +283,7 @@ def test_subset_set_with_mask(using_copy_on_write):
subset[mask] = 0
else:
with pd.option_context("chained_assignment", "warn"):
with tm.assert_produces_warning(com.SettingWithCopyWarning):
with tm.assert_produces_warning(SettingWithCopyWarning):
subset[mask] = 0

expected = DataFrame(
Expand All @@ -309,7 +310,7 @@ def test_subset_set_column(using_copy_on_write):
subset["a"] = np.array([10, 11], dtype="int64")
else:
with pd.option_context("chained_assignment", "warn"):
with tm.assert_produces_warning(com.SettingWithCopyWarning):
with tm.assert_produces_warning(SettingWithCopyWarning):
subset["a"] = np.array([10, 11], dtype="int64")

subset._mgr._verify_integrity()
Expand Down Expand Up @@ -340,7 +341,7 @@ def test_subset_set_column_with_loc(using_copy_on_write, using_array_manager, dt
# warnings and only assert the SettingWithCopyWarning
raise_on_extra_warnings = False if using_array_manager else True
with tm.assert_produces_warning(
com.SettingWithCopyWarning,
SettingWithCopyWarning,
raise_on_extra_warnings=raise_on_extra_warnings,
):
subset.loc[:, "a"] = np.array([10, 11], dtype="int64")
Expand Down Expand Up @@ -377,7 +378,7 @@ def test_subset_set_column_with_loc2(using_copy_on_write, using_array_manager):
# warnings and only assert the SettingWithCopyWarning
raise_on_extra_warnings = False if using_array_manager else True
with tm.assert_produces_warning(
com.SettingWithCopyWarning,
SettingWithCopyWarning,
raise_on_extra_warnings=raise_on_extra_warnings,
):
subset.loc[:, "a"] = 0
Expand Down Expand Up @@ -410,7 +411,7 @@ def test_subset_set_columns(using_copy_on_write, dtype):
subset[["a", "c"]] = 0
else:
with pd.option_context("chained_assignment", "warn"):
with tm.assert_produces_warning(com.SettingWithCopyWarning):
with tm.assert_produces_warning(SettingWithCopyWarning):
subset[["a", "c"]] = 0

subset._mgr._verify_integrity()
Expand Down Expand Up @@ -443,7 +444,7 @@ def test_subset_set_with_column_indexer(
# The (i)loc[:, col] inplace deprecation gets triggered here, ignore those
# warnings and only assert the SettingWithCopyWarning
with tm.assert_produces_warning(
com.SettingWithCopyWarning, raise_on_extra_warnings=False
SettingWithCopyWarning, raise_on_extra_warnings=False
):
subset.loc[:, indexer] = 0

Expand Down Expand Up @@ -580,7 +581,7 @@ def test_column_as_series(using_copy_on_write, using_array_manager):
s[0] = 0
else:
with pd.option_context("chained_assignment", "warn"):
with tm.assert_produces_warning(com.SettingWithCopyWarning):
with tm.assert_produces_warning(SettingWithCopyWarning):
s[0] = 0

expected = Series([0, 2, 3], name="a")
Expand All @@ -607,7 +608,7 @@ def test_column_as_series_set_with_upcast(using_copy_on_write, using_array_manag
s[0] = "foo"
else:
with pd.option_context("chained_assignment", "warn"):
with tm.assert_produces_warning(com.SettingWithCopyWarning):
with tm.assert_produces_warning(SettingWithCopyWarning):
s[0] = "foo"

expected = Series(["foo", 2, 3], dtype=object, name="a")
Expand Down
12 changes: 7 additions & 5 deletions pandas/tests/indexing/test_chaining_and_caching.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,10 @@
import numpy as np
import pytest

from pandas.errors import SettingWithCopyError
from pandas.errors import (
SettingWithCopyError,
SettingWithCopyWarning,
)
import pandas.util._test_decorators as td

import pandas as pd
Expand All @@ -15,7 +18,6 @@
option_context,
)
import pandas._testing as tm
import pandas.core.common as com

msg = "A value is trying to be set on a copy of a slice from a DataFrame"

Expand Down Expand Up @@ -415,7 +417,7 @@ def test_setting_with_copy_bug_no_warning(self):
def test_detect_chained_assignment_warnings_errors(self):
df = DataFrame({"A": ["aaa", "bbb", "ccc"], "B": [1, 2, 3]})
with option_context("chained_assignment", "warn"):
with tm.assert_produces_warning(com.SettingWithCopyWarning):
with tm.assert_produces_warning(SettingWithCopyWarning):
df.loc[0]["A"] = 111

with option_context("chained_assignment", "raise"):
Expand All @@ -427,7 +429,7 @@ def test_detect_chained_assignment_warnings_filter_and_dupe_cols(self):
with option_context("chained_assignment", "warn"):
df = DataFrame([[1, 2, 3], [4, 5, 6], [7, 8, -9]], columns=["a", "a", "c"])

with tm.assert_produces_warning(com.SettingWithCopyWarning):
with tm.assert_produces_warning(SettingWithCopyWarning):
df.c.loc[df.c > 0] = None

expected = DataFrame(
Expand All @@ -441,7 +443,7 @@ def test_detect_chained_assignment_warning_stacklevel(self, rhs):
df = DataFrame(np.arange(25).reshape(5, 5))
chained = df.loc[:3]
with option_context("chained_assignment", "warn"):
with tm.assert_produces_warning(com.SettingWithCopyWarning) as t:
with tm.assert_produces_warning(SettingWithCopyWarning) as t:
chained[2] = rhs
assert t[0].filename == __file__

Expand Down
1 change: 1 addition & 0 deletions pandas/tests/test_errors.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
"DataError",
"SpecificationError",
"SettingWithCopyError",
"SettingWithCopyWarning",
],
)
def test_exception_importable(exc):
Expand Down