|
1 | 1 | """ Test cases for DataFrame.plot """
|
2 |
| - |
3 | 2 | from datetime import date, datetime
|
4 | 3 | import itertools
|
| 4 | +import re |
5 | 5 | import string
|
6 | 6 | import warnings
|
7 | 7 |
|
@@ -358,10 +358,10 @@ def test_negative_log(self):
|
358 | 358 | index=list(string.ascii_letters[:6]),
|
359 | 359 | columns=["x", "y", "z", "four"],
|
360 | 360 | )
|
361 |
| - |
362 |
| - with pytest.raises(ValueError): |
| 361 | + msg = "Log-y scales are not supported in area plot" |
| 362 | + with pytest.raises(ValueError, match=msg): |
363 | 363 | df.plot.area(logy=True)
|
364 |
| - with pytest.raises(ValueError): |
| 364 | + with pytest.raises(ValueError, match=msg): |
365 | 365 | df.plot.area(loglog=True)
|
366 | 366 |
|
367 | 367 | def _compare_stacked_y_cood(self, normal_lines, stacked_lines):
|
@@ -406,7 +406,12 @@ def test_line_area_stacked(self):
|
406 | 406 | self._compare_stacked_y_cood(ax1.lines[2:], ax2.lines[2:])
|
407 | 407 |
|
408 | 408 | _check_plot_works(mixed_df.plot, stacked=False)
|
409 |
| - with pytest.raises(ValueError): |
| 409 | + msg = ( |
| 410 | + "When stacked is True, each column must be either all positive or " |
| 411 | + "all negative. Column 'w' contains both positive and negative " |
| 412 | + "values" |
| 413 | + ) |
| 414 | + with pytest.raises(ValueError, match=msg): |
410 | 415 | mixed_df.plot(stacked=True)
|
411 | 416 |
|
412 | 417 | # Use an index with strictly positive values, preventing
|
@@ -650,9 +655,11 @@ def test_plot_scatter(self):
|
650 | 655 | _check_plot_works(df.plot.scatter, x="x", y="y")
|
651 | 656 | _check_plot_works(df.plot.scatter, x=1, y=2)
|
652 | 657 |
|
653 |
| - with pytest.raises(TypeError): |
| 658 | + msg = re.escape("scatter() missing 1 required positional argument: 'y'") |
| 659 | + with pytest.raises(TypeError, match=msg): |
654 | 660 | df.plot.scatter(x="x")
|
655 |
| - with pytest.raises(TypeError): |
| 661 | + msg = re.escape("scatter() missing 1 required positional argument: 'x'") |
| 662 | + with pytest.raises(TypeError, match=msg): |
656 | 663 | df.plot.scatter(y="y")
|
657 | 664 |
|
658 | 665 | # GH 6951
|
@@ -850,8 +857,9 @@ def test_boxplot_return_type(self):
|
850 | 857 | index=list(string.ascii_letters[:6]),
|
851 | 858 | columns=["one", "two", "three", "four"],
|
852 | 859 | )
|
853 |
| - with pytest.raises(ValueError): |
854 |
| - df.plot.box(return_type="NOTATYPE") |
| 860 | + msg = "return_type must be {None, 'axes', 'dict', 'both'}" |
| 861 | + with pytest.raises(ValueError, match=msg): |
| 862 | + df.plot.box(return_type="not_a_type") |
855 | 863 |
|
856 | 864 | result = df.plot.box(return_type="dict")
|
857 | 865 | self._check_box_return_type(result, "dict")
|
@@ -1309,44 +1317,47 @@ def test_partially_invalid_plot_data(self):
|
1309 | 1317 | df = DataFrame(np.random.randn(10, 2), dtype=object)
|
1310 | 1318 | df[np.random.rand(df.shape[0]) > 0.5] = "a"
|
1311 | 1319 | for kind in plotting.PlotAccessor._common_kinds:
|
1312 |
| - |
1313 | 1320 | msg = "no numeric data to plot"
|
1314 | 1321 | with pytest.raises(TypeError, match=msg):
|
1315 | 1322 | df.plot(kind=kind)
|
1316 | 1323 |
|
1317 | 1324 | with tm.RNGContext(42):
|
1318 | 1325 | # area plot doesn't support positive/negative mixed data
|
1319 |
| - kinds = ["area"] |
1320 | 1326 | df = DataFrame(np.random.rand(10, 2), dtype=object)
|
1321 | 1327 | df[np.random.rand(df.shape[0]) > 0.5] = "a"
|
1322 |
| - for kind in kinds: |
1323 |
| - with pytest.raises(TypeError): |
1324 |
| - df.plot(kind=kind) |
| 1328 | + with pytest.raises(TypeError, match="no numeric data to plot"): |
| 1329 | + df.plot(kind="area") |
1325 | 1330 |
|
1326 | 1331 | def test_invalid_kind(self):
|
1327 | 1332 | df = DataFrame(np.random.randn(10, 2))
|
1328 |
| - with pytest.raises(ValueError): |
1329 |
| - df.plot(kind="aasdf") |
| 1333 | + msg = "invalid_plot_kind is not a valid plot kind" |
| 1334 | + with pytest.raises(ValueError, match=msg): |
| 1335 | + df.plot(kind="invalid_plot_kind") |
1330 | 1336 |
|
1331 | 1337 | @pytest.mark.parametrize(
|
1332 | 1338 | "x,y,lbl",
|
1333 | 1339 | [
|
1334 | 1340 | (["B", "C"], "A", "a"),
|
1335 | 1341 | (["A"], ["B", "C"], ["b", "c"]),
|
1336 |
| - ("A", ["B", "C"], "badlabel"), |
1337 | 1342 | ],
|
1338 | 1343 | )
|
1339 | 1344 | def test_invalid_xy_args(self, x, y, lbl):
|
1340 | 1345 | # GH 18671, 19699 allows y to be list-like but not x
|
1341 | 1346 | df = DataFrame({"A": [1, 2], "B": [3, 4], "C": [5, 6]})
|
1342 |
| - with pytest.raises(ValueError): |
| 1347 | + with pytest.raises(ValueError, match="x must be a label or position"): |
1343 | 1348 | df.plot(x=x, y=y, label=lbl)
|
1344 | 1349 |
|
| 1350 | + def test_bad_label(self): |
| 1351 | + df = DataFrame({"A": [1, 2], "B": [3, 4], "C": [5, 6]}) |
| 1352 | + msg = "label should be list-like and same length as y" |
| 1353 | + with pytest.raises(ValueError, match=msg): |
| 1354 | + df.plot(x="A", y=["B", "C"], label="bad_label") |
| 1355 | + |
1345 | 1356 | @pytest.mark.parametrize("x,y", [("A", "B"), (["A"], "B")])
|
1346 | 1357 | def test_invalid_xy_args_dup_cols(self, x, y):
|
1347 | 1358 | # GH 18671, 19699 allows y to be list-like but not x
|
1348 | 1359 | df = DataFrame([[1, 3, 5], [2, 4, 6]], columns=list("AAB"))
|
1349 |
| - with pytest.raises(ValueError): |
| 1360 | + with pytest.raises(ValueError, match="x must be a label or position"): |
1350 | 1361 | df.plot(x=x, y=y)
|
1351 | 1362 |
|
1352 | 1363 | @pytest.mark.parametrize(
|
@@ -1416,7 +1427,8 @@ def test_pie_df(self):
|
1416 | 1427 | columns=["X", "Y", "Z"],
|
1417 | 1428 | index=["a", "b", "c", "d", "e"],
|
1418 | 1429 | )
|
1419 |
| - with pytest.raises(ValueError): |
| 1430 | + msg = "pie requires either y column or 'subplots=True'" |
| 1431 | + with pytest.raises(ValueError, match=msg): |
1420 | 1432 | df.plot.pie()
|
1421 | 1433 |
|
1422 | 1434 | ax = _check_plot_works(df.plot.pie, y="Y")
|
@@ -1520,11 +1532,11 @@ def test_errorbar_plot(self):
|
1520 | 1532 | ax = _check_plot_works(s_df.plot, y="y", x="x", yerr=yerr)
|
1521 | 1533 | self._check_has_errorbars(ax, xerr=0, yerr=1)
|
1522 | 1534 |
|
1523 |
| - with pytest.raises(ValueError): |
| 1535 | + with tm.external_error_raised(ValueError): |
1524 | 1536 | df.plot(yerr=np.random.randn(11))
|
1525 | 1537 |
|
1526 | 1538 | df_err = DataFrame({"x": ["zzz"] * 12, "y": ["zzz"] * 12})
|
1527 |
| - with pytest.raises((ValueError, TypeError)): |
| 1539 | + with tm.external_error_raised(TypeError): |
1528 | 1540 | df.plot(yerr=df_err)
|
1529 | 1541 |
|
1530 | 1542 | @pytest.mark.parametrize("kind", ["line", "bar", "barh"])
|
@@ -1647,7 +1659,10 @@ def test_errorbar_asymmetrical(self):
|
1647 | 1659 | expected_0_0 = err[0, :, 0] * np.array([-1, 1])
|
1648 | 1660 | tm.assert_almost_equal(yerr_0_0, expected_0_0)
|
1649 | 1661 |
|
1650 |
| - with pytest.raises(ValueError): |
| 1662 | + msg = re.escape( |
| 1663 | + "Asymmetrical error bars should be provided with the shape (3, 2, 5)" |
| 1664 | + ) |
| 1665 | + with pytest.raises(ValueError, match=msg): |
1651 | 1666 | df.plot(yerr=err.T)
|
1652 | 1667 |
|
1653 | 1668 | tm.close()
|
@@ -1837,9 +1852,10 @@ def test_memory_leak(self):
|
1837 | 1852 | tm.close()
|
1838 | 1853 | # force a garbage collection
|
1839 | 1854 | gc.collect()
|
| 1855 | + msg = "weakly-referenced object no longer exists" |
1840 | 1856 | for key in results:
|
1841 | 1857 | # check that every plot was collected
|
1842 |
| - with pytest.raises(ReferenceError): |
| 1858 | + with pytest.raises(ReferenceError, match=msg): |
1843 | 1859 | # need to actually access something to get an error
|
1844 | 1860 | results[key].lines
|
1845 | 1861 |
|
@@ -2095,7 +2111,7 @@ def test_plot_no_rows(self):
|
2095 | 2111 |
|
2096 | 2112 | def test_plot_no_numeric_data(self):
|
2097 | 2113 | df = DataFrame(["a", "b", "c"])
|
2098 |
| - with pytest.raises(TypeError): |
| 2114 | + with pytest.raises(TypeError, match="no numeric data to plot"): |
2099 | 2115 | df.plot()
|
2100 | 2116 |
|
2101 | 2117 | def test_missing_markers_legend(self):
|
|
0 commit comments