diff --git a/conftest.py b/conftest.py new file mode 100644 index 00000000..7918697f --- /dev/null +++ b/conftest.py @@ -0,0 +1,26 @@ +# ----- IMPORTANT ----- +# See GL#80 & GL#81 +# This file can be deleted once ``_indices.py`` is fully removed. + +import pytest + +def warning_depr(x): + return pytest.warns( + FutureWarning, match=f"{x} is deprecated and will be removed on 2025-01-01." + ) + +def warning_invalid(x): + return pytest.warns(RuntimeWarning, match=f"invalid value encountered in {x}") + +warning_div_zero = pytest.warns(RuntimeWarning, match="divide by zero encountered") + + +def pytest_configure(config): + pytest.warning_depr = warning_depr + pytest.warning_invalid = warning_invalid + pytest.warning_div_zero = warning_div_zero + + +def pytest_ignore_collect(collection_path): + return True if str(collection_path).endswith("_indices.py") else False + diff --git a/inequality/pen.py b/inequality/pen.py index 5ab5011a..fb3f6f76 100644 --- a/inequality/pen.py +++ b/inequality/pen.py @@ -137,7 +137,7 @@ def pen( df_sorted = df_repeated.sort_values(by=col).reset_index(drop=True) unique_obs = df[name].unique() - colors = plt.cm.get_cmap("tab20", len(unique_obs)) + colors = plt.get_cmap("tab20", len(unique_obs)) color_map = {state: colors(i) for i, state in enumerate(unique_obs)} bar_colors = df_sorted[name].map(color_map) diff --git a/inequality/tests/test_indices.py b/inequality/tests/test_indices.py index a0f76e7f..dd4a98df 100644 --- a/inequality/tests/test_indices.py +++ b/inequality/tests/test_indices.py @@ -48,61 +48,81 @@ class TestAbundance: def test_abundance(self): known = 2 - observed = abundance(x) + with pytest.warning_depr("abundance"): + observed = abundance(x) assert known == observed class TestMargalevMD: def test_margalev_md(self): known = 0.40242960438184466 - observed = margalev_md(x) + with pytest.warning_depr("abundance"), pytest.warning_depr("margalev_md"): + observed = margalev_md(x) assert known == pytest.approx(observed) class TestMenhinickMI: def test_menhinick_mi(self): known = 0.2886751345948129 - observed = menhinick_mi(x) + with pytest.warning_depr("abundance"), pytest.warning_depr("menhinick_mi"): + observed = menhinick_mi(x) assert known == pytest.approx(observed) class TestSimpsonSO: def test_simpson_so(self): known = 0.5909090909090909 - observed = simpson_so(x) + with pytest.warning_depr("simpson_so"): + observed = simpson_so(x) assert known == pytest.approx(observed) class TestSimpsonSD: def test_simpson_sd(self): known = 0.40909090909090906 - observed = simpson_sd(x) + with pytest.warning_depr("simpson_so"), pytest.warning_depr("simpson_sd"): + observed = simpson_sd(x) assert known == pytest.approx(observed) class TestHerfindahlHD: def test_herfindahl_hd(self): known = 0.625 - observed = herfindahl_hd(x) + with pytest.warning_depr("herfindahl_hd"): + observed = herfindahl_hd(x) assert known == pytest.approx(observed) class TestTheilTH: def test_theil_th(self): known = 0.15106563978903298 - observed = theil_th(x, ridz=True) + with pytest.warning_depr("theil_th"): + observed = theil_th(x, ridz=True) assert known == pytest.approx(observed) - with pytest.warns(RuntimeWarning, match="divide by zero encountered"): + with ( + pytest.warning_depr("theil_th"), + pytest.warning_div_zero, + pytest.warning_invalid("subtract"), + pytest.warning_invalid("multiply"), + ): observed = theil_th(x, ridz=False) assert numpy.isnan(observed) # test brute comparison - known = theil_th_brute(x, ridz=True) - observed = theil_th(x, ridz=True) + with pytest.warning_depr("theil_th_brute"): + known = theil_th_brute(x, ridz=True) + with pytest.warning_depr("theil_th"): + observed = theil_th(x, ridz=True) assert known == pytest.approx(observed) - with pytest.warns(RuntimeWarning, match="divide by zero encountered"): + with ( + pytest.warning_depr("theil_th_brute"), + pytest.warning_div_zero, + pytest.warning_invalid("scalar multiply"), + pytest.warning_invalid("multiply"), + pytest.warning_invalid("scalar subtract"), + ): observed = theil_th_brute(x, ridz=False) assert numpy.isnan(observed) @@ -110,117 +130,143 @@ def test_theil_th(self): class TestFractionalizationGS: def test_fractionalization_gs(self): known = 0.375 - observed = fractionalization_gs(x) + with ( + pytest.warning_depr("herfindahl_hd"), + pytest.warning_depr("fractionalization_gs"), + ): + observed = fractionalization_gs(x) assert known == pytest.approx(observed) class TestPolarization: def test_polarization(self): - with pytest.raises(RuntimeError, match="Not currently implemented."): + with ( + pytest.raises(RuntimeError, match="Not currently implemented."), + pytest.warning_depr("polarization"), + ): polarization(None) class TestShannonSE: def test_shannon_se(self): known = 1.094070862104929 - observed = shannon_se(y) + with pytest.warning_depr("shannon_se"): + observed = shannon_se(y) assert known == pytest.approx(observed) class TestGiniGI: def test_gini_gi(self): known = 0.05128205128205132 - observed = gini_gi(y) + with pytest.warning_depr("_gini"), pytest.warning_depr("gini_gi"): + observed = gini_gi(y) assert known == pytest.approx(observed) class TestGiniGIG: def test_gini_gig(self): known = numpy.array([0.125, 0.32894737, 0.18181818]) - observed = gini_gig(y) + with pytest.warning_depr("_gini"), pytest.warning_depr("gini_gig"): + observed = gini_gig(y) numpy.testing.assert_array_almost_equal(known, observed) class TestGiniGIM: def test_gini_gi_m(self): known = 0.05128205128205132 - observed = gini_gi_m(y) + with pytest.warning_depr("gini_gi_m"): + observed = gini_gi_m(y) assert known == pytest.approx(observed) class TestHooverHI: def test_hoover_hi(self): known = 0.041025641025641046 - observed = hoover_hi(y) + with pytest.warning_depr("hoover_hi"): + observed = hoover_hi(y) assert known == pytest.approx(observed) class TestSimilarityWWD: def test_similarity_w_wd(self): known = 0.5818596340322582 - observed = similarity_w_wd(y, tau) + with pytest.warning_depr("similarity_w_wd"): + observed = similarity_w_wd(y, tau) assert known == pytest.approx(observed) class TestSegregationGSG: def test_segregation_gsg(self): known = numpy.array([0.18292683, 0.24713959, 0.09725159]) - observed = segregation_gsg(y) + with pytest.warning_depr("segregation_gsg"): + observed = segregation_gsg(y) numpy.testing.assert_array_almost_equal(known, observed) class TestModifiedSegregationMSG: def test_modified_segregation_msg(self): known = numpy.array([0.0852071, 0.10224852, 0.0435503]) - observed = modified_segregation_msg(y) + with ( + pytest.warning_depr("segregation_gsg"), + pytest.warning_depr("modified_segregation_msg"), + ): + observed = modified_segregation_msg(y) numpy.testing.assert_array_almost_equal(known, observed) class TestIsolationISG: def test_isolation_isg(self): known = numpy.array([1.0732699, 1.21995329, 1.0227105]) - observed = isolation_isg(y) + with pytest.warning_depr("isolation_isg"): + observed = isolation_isg(y) numpy.testing.assert_array_almost_equal(known, observed) class TestIsolationII: def test_isolation_ii(self): known = numpy.array([1.1161596, 1.31080357, 1.03432983]) - observed = isolation_ii(y) + with pytest.warning_depr("isolation_ii"): + observed = isolation_ii(y) numpy.testing.assert_array_almost_equal(known, observed) class TestEllisonGlaeserEGG: def test_ellison_glaeser_egg(self): known = numpy.array([0.0544994, 0.01624183, 0.01014058, 0.02880251]) - observed = ellison_glaeser_egg(z) + with pytest.warning_depr("ellison_glaeser_egg"): + observed = ellison_glaeser_egg(z) numpy.testing.assert_array_almost_equal(known, observed) known = numpy.array([-1.0617873, -2.39452501, -1.45991648, -1.11740985]) - observed = ellison_glaeser_egg(z, hs=v) + with pytest.warning_depr("ellison_glaeser_egg"): + observed = ellison_glaeser_egg(z, hs=v) numpy.testing.assert_array_almost_equal(known, observed) class TestEllisonGlaeserEGGPop: def test_ellison_glaeser_egg_pop(self): known = numpy.array([-0.02150826, 0.01329858, -0.03894556]) - observed = ellison_glaeser_egg_pop(y) + with pytest.warning_depr("ellison_glaeser_egg_pop"): + observed = ellison_glaeser_egg_pop(y) numpy.testing.assert_array_almost_equal(known, observed) class TestMaurelSedillotMSG: def test_maurel_sedillot_msg(self): known = numpy.array([0.07858256, 0.03597749, 0.03937436, -0.00904911]) - observed = maurel_sedillot_msg(z) + with pytest.warning_depr("maurel_sedillot_msg"): + observed = maurel_sedillot_msg(z) numpy.testing.assert_array_almost_equal(known, observed) known = numpy.array([-1.01010171, -2.32421555, -1.38868998, -1.20049894]) - observed = maurel_sedillot_msg(z, hs=v.round(3)) + with pytest.warning_depr("maurel_sedillot_msg"): + observed = maurel_sedillot_msg(z, hs=v.round(3)) numpy.testing.assert_array_almost_equal(known, observed) class TestMaurelSedillotMSGPop: def test_maurel_sedillot_msg_pop(self): known = numpy.array([-0.05503571, 0.04414672, -0.02866628]) - observed = maurel_sedillot_msg_pop(y) + with pytest.warning_depr("maurel_sedillot_msg_pop"): + observed = maurel_sedillot_msg_pop(y) numpy.testing.assert_array_almost_equal(known, observed) diff --git a/inequality/tests/test_schutz.py b/inequality/tests/test_schutz.py index 1a90d1e6..031f1afa 100644 --- a/inequality/tests/test_schutz.py +++ b/inequality/tests/test_schutz.py @@ -12,6 +12,14 @@ def example_dataframe(): return pd.DataFrame(data) +@pytest.fixture +def noninteractive_warning(): + return pytest.warns( + UserWarning, + match="FigureCanvasAgg is non-interactive, and thus cannot be shown", + ) + + def test_schutz_distance(example_dataframe): schutz_obj = Schutz(example_dataframe, "Y") expected_distance = 0.15 @@ -32,15 +40,16 @@ def test_schutz_coefficient(example_dataframe): assert pytest.approx(schutz_obj.coefficient, 0.1) == expected_coefficient -def test_schutz_plot_runs_without_errors(example_dataframe): +def test_schutz_plot_runs_without_errors(example_dataframe, noninteractive_warning): schutz_obj = Schutz(example_dataframe, "Y") try: - schutz_obj.plot() + with noninteractive_warning: + schutz_obj.plot() except Exception as e: pytest.fail(f"Plotting failed: {e}") -def test_schutz_plot_output(example_dataframe, tmpdir): +def test_schutz_plot_output(example_dataframe, tmpdir, noninteractive_warning): """Test if the plot output matches the expected result by saving the plot and comparing it.""" schutz_obj = Schutz(example_dataframe, "Y") @@ -48,7 +57,8 @@ def test_schutz_plot_output(example_dataframe, tmpdir): # Save the plot to a temporary directory plot_file = os.path.join(tmpdir, "schutz_plot.png") plt.figure() - schutz_obj.plot() + with noninteractive_warning: + schutz_obj.plot() plt.savefig(plot_file) plt.close()