Skip to content

Commit 1a12c41

Browse files
TST: Fail on warning (#22699)
1 parent 79f7762 commit 1a12c41

File tree

106 files changed

+2677
-2298
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

106 files changed

+2677
-2298
lines changed

.travis.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ matrix:
6464
# In allow_failures
6565
- dist: trusty
6666
env:
67-
- JOB="3.6, NumPy dev" ENV_FILE="ci/travis-36-numpydev.yaml" TEST_ARGS="--skip-slow --skip-network" PANDAS_TESTING_MODE="deprecate"
67+
- JOB="3.7, NumPy dev" ENV_FILE="ci/travis-37-numpydev.yaml" TEST_ARGS="--skip-slow --skip-network -W error" PANDAS_TESTING_MODE="deprecate"
6868
addons:
6969
apt:
7070
packages:
@@ -79,7 +79,7 @@ matrix:
7979
- JOB="3.6, slow" ENV_FILE="ci/travis-36-slow.yaml" SLOW=true
8080
- dist: trusty
8181
env:
82-
- JOB="3.6, NumPy dev" ENV_FILE="ci/travis-36-numpydev.yaml" TEST_ARGS="--skip-slow --skip-network" PANDAS_TESTING_MODE="deprecate"
82+
- JOB="3.7, NumPy dev" ENV_FILE="ci/travis-37-numpydev.yaml" TEST_ARGS="--skip-slow --skip-network -W error" PANDAS_TESTING_MODE="deprecate"
8383
addons:
8484
apt:
8585
packages:

ci/travis-36-numpydev.yaml renamed to ci/travis-37-numpydev.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ name: pandas
22
channels:
33
- defaults
44
dependencies:
5-
- python=3.6*
5+
- python=3.7*
66
- pytz
77
- Cython>=0.28.2
88
# universal

doc/source/contributing.rst

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -632,6 +632,14 @@ Otherwise, you need to do it manually:
632632
warnings.warn('Use new_func instead.', FutureWarning, stacklevel=2)
633633
new_func()
634634
635+
You'll also need to
636+
637+
1. write a new test that asserts a warning is issued when calling with the deprecated argument
638+
2. Update all of pandas existing tests and code to use the new argument
639+
640+
See :ref:`contributing.warnings` for more.
641+
642+
635643
.. _contributing.ci:
636644

637645
Testing With Continuous Integration
@@ -859,6 +867,55 @@ preferred if the inputs or logic are simple, with Hypothesis tests reserved
859867
for cases with complex logic or where there are too many combinations of
860868
options or subtle interactions to test (or think of!) all of them.
861869

870+
.. _contributing.warnings:
871+
872+
Testing Warnings
873+
~~~~~~~~~~~~~~~~
874+
875+
By default, one of pandas CI workers will fail if any unhandled warnings are emitted.
876+
877+
If your change involves checking that a warning is actually emitted, use
878+
``tm.assert_produces_warning(ExpectedWarning)``.
879+
880+
881+
.. code-block:: python
882+
883+
with tm.assert_prodcues_warning(FutureWarning):
884+
df.some_operation()
885+
886+
We prefer this to the ``pytest.warns`` context manager because ours checks that the warning's
887+
stacklevel is set correctly. The stacklevel is what ensure the *user's* file name and line number
888+
is printed in the warning, rather than something internal to pandas. It represents the number of
889+
function calls from user code (e.g. ``df.some_operation()``) to the function that actually emits
890+
the warning. Our linter will fail the build if you use ``pytest.warns`` in a test.
891+
892+
If you have a test that would emit a warning, but you aren't actually testing the
893+
warning itself (say because it's going to be removed in the future, or because we're
894+
matching a 3rd-party library's behavior), then use ``pytest.mark.filterwarnings`` to
895+
ignore the error.
896+
897+
.. code-block:: python
898+
899+
@pytest.mark.filterwarnings("ignore:msg:category")
900+
def test_thing(self):
901+
...
902+
903+
If the test generates a warning of class ``category`` whose message starts
904+
with ``msg``, the warning will be ignored and the test will pass.
905+
906+
If you need finer-grained control, you can use Python's usual
907+
`warnings module <https://docs.python.org/3/library/warnings.html>`__
908+
to control whether a warning is ignored / raised at different places within
909+
a single test.
910+
911+
.. code-block:: python
912+
913+
with warch.catch_warnings():
914+
warnings.simplefilter("ignore", FutureWarning)
915+
# Or use warnings.filterwarnings(...)
916+
917+
Alternatively, consider breaking up the unit test.
918+
862919

863920
Running the test suite
864921
----------------------

pandas/compat/__init__.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
import struct
3939
import inspect
4040
from collections import namedtuple
41+
import collections
4142

4243
PY2 = sys.version_info[0] == 2
4344
PY3 = sys.version_info[0] >= 3
@@ -135,6 +136,11 @@ def lfilter(*args, **kwargs):
135136

136137
from importlib import reload
137138
reload = reload
139+
Hashable = collections.abc.Hashable
140+
Iterable = collections.abc.Iterable
141+
Mapping = collections.abc.Mapping
142+
Sequence = collections.abc.Sequence
143+
Sized = collections.abc.Sized
138144

139145
else:
140146
# Python 2
@@ -190,6 +196,12 @@ def get_range_parameters(data):
190196

191197
reload = builtins.reload
192198

199+
Hashable = collections.Hashable
200+
Iterable = collections.Iterable
201+
Mapping = collections.Mapping
202+
Sequence = collections.Sequence
203+
Sized = collections.Sized
204+
193205
if PY2:
194206
def iteritems(obj, **kw):
195207
return obj.iteritems(**kw)

pandas/compat/chainmap_impl.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,11 @@
1-
from collections import MutableMapping
1+
import sys
2+
3+
PY3 = sys.version_info[0] >= 3
4+
5+
if PY3:
6+
from collections.abc import MutableMapping
7+
else:
8+
from collections import MutableMapping
29

310
try:
411
from thread import get_ident

pandas/core/algorithms.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
intended for public consumption
44
"""
55
from __future__ import division
6-
from warnings import warn, catch_warnings
6+
from warnings import warn, catch_warnings, simplefilter
77
from textwrap import dedent
88

99
import numpy as np
@@ -91,7 +91,8 @@ def _ensure_data(values, dtype=None):
9191

9292
# ignore the fact that we are casting to float
9393
# which discards complex parts
94-
with catch_warnings(record=True):
94+
with catch_warnings():
95+
simplefilter("ignore", np.ComplexWarning)
9596
values = ensure_float64(values)
9697
return values, 'float64', 'float64'
9798

pandas/core/arrays/datetimelike.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ def cmp_method(self, other):
5959
# numpy will show a DeprecationWarning on invalid elementwise
6060
# comparisons, this will raise in the future
6161
with warnings.catch_warnings(record=True):
62+
warnings.filterwarnings("ignore", "elementwise", FutureWarning)
6263
with np.errstate(all='ignore'):
6364
result = op(self.values, np.asarray(other))
6465

pandas/core/arrays/integer.py

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55

66
from pandas._libs.lib import infer_dtype
77
from pandas.util._decorators import cache_readonly
8-
from pandas.compat import u, range
8+
from pandas.compat import u, range, string_types
99
from pandas.compat import set_function_name
1010

1111
from pandas.core.dtypes.cast import astype_nansafe
@@ -147,6 +147,11 @@ def coerce_to_array(values, dtype, mask=None, copy=False):
147147
dtype = values.dtype
148148

149149
if dtype is not None:
150+
if (isinstance(dtype, string_types) and
151+
(dtype.startswith("Int") or dtype.startswith("UInt"))):
152+
# Avoid DeprecationWarning from NumPy about np.dtype("Int64")
153+
# https://github.com/numpy/numpy/pull/7476
154+
dtype = dtype.lower()
150155
if not issubclass(type(dtype), _IntegerDtype):
151156
try:
152157
dtype = _dtypes[str(np.dtype(dtype))]
@@ -507,7 +512,8 @@ def cmp_method(self, other):
507512

508513
# numpy will show a DeprecationWarning on invalid elementwise
509514
# comparisons, this will raise in the future
510-
with warnings.catch_warnings(record=True):
515+
with warnings.catch_warnings():
516+
warnings.filterwarnings("ignore", "elementwise", FutureWarning)
511517
with np.errstate(all='ignore'):
512518
result = op(self._data, other)
513519

pandas/core/common.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -356,7 +356,7 @@ def standardize_mapping(into):
356356
return partial(
357357
collections.defaultdict, into.default_factory)
358358
into = type(into)
359-
if not issubclass(into, collections.Mapping):
359+
if not issubclass(into, compat.Mapping):
360360
raise TypeError('unsupported type: {into}'.format(into=into))
361361
elif into == collections.defaultdict:
362362
raise TypeError(

pandas/core/computation/eval.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -323,6 +323,7 @@ def eval(expr, parser='pandas', engine=None, truediv=True,
323323
# to use a non-numeric indexer
324324
try:
325325
with warnings.catch_warnings(record=True):
326+
# TODO: Filter the warnings we actually care about here.
326327
target[assigner] = ret
327328
except (TypeError, IndexError):
328329
raise ValueError("Cannot assign expression output to target")

0 commit comments

Comments
 (0)