From 911156021b75f5852ebd934c0ee817bab5b362e1 Mon Sep 17 00:00:00 2001 From: Matthew Roeschke Date: Sat, 29 Jan 2022 14:44:30 -0800 Subject: [PATCH 1/3] TST: Disable functionality that hangs Azure CI --- ci/run_tests.sh | 2 +- pandas/tests/io/excel/conftest.py | 4 +++- pandas/tests/io/excel/test_readers.py | 6 ++---- pandas/tests/io/parser/conftest.py | 18 ++++++++++++++++-- pandas/tests/io/test_sql.py | 8 ++++++++ pandas/tests/window/test_numba.py | 15 +++++++++++++++ pandas/tests/window/test_online.py | 15 +++++++++++++++ pandas/util/_test_decorators.py | 3 ++- 8 files changed, 62 insertions(+), 9 deletions(-) diff --git a/ci/run_tests.sh b/ci/run_tests.sh index 020a3ed7f265c..344982920273e 100755 --- a/ci/run_tests.sh +++ b/ci/run_tests.sh @@ -24,7 +24,7 @@ if [[ $(uname) == "Linux" && -z $DISPLAY ]]; then XVFB="xvfb-run " fi -PYTEST_CMD="${XVFB}pytest -r fEs -m \"$PATTERN\" -n $PYTEST_WORKERS --dist=loadfile $TEST_ARGS $COVERAGE $PYTEST_TARGET" +PYTEST_CMD="${XVFB}pytest -v -r fEs -m \"$PATTERN\" -n $PYTEST_WORKERS --dist=loadfile $TEST_ARGS $COVERAGE $PYTEST_TARGET" if [[ $(uname) != "Linux" && $(uname) != "Darwin" ]]; then PYTEST_CMD="$PYTEST_CMD --ignore=pandas/tests/plotting/" diff --git a/pandas/tests/io/excel/conftest.py b/pandas/tests/io/excel/conftest.py index 0455e0d61ad97..4ce06c01892d9 100644 --- a/pandas/tests/io/excel/conftest.py +++ b/pandas/tests/io/excel/conftest.py @@ -1,5 +1,6 @@ import pytest +from pandas.compat import is_platform_windows import pandas.util._test_decorators as td import pandas._testing as tm @@ -43,7 +44,8 @@ def read_ext(request): return request.param -@pytest.fixture(autouse=True) +# Checking for file leaks can hang on Windows CI +@pytest.fixture(autouse=not is_platform_windows()) def check_for_file_leaks(): """ Fixture to run around every test to ensure that we are not leaking files. diff --git a/pandas/tests/io/excel/test_readers.py b/pandas/tests/io/excel/test_readers.py index 589c98721f139..119457a3d4025 100644 --- a/pandas/tests/io/excel/test_readers.py +++ b/pandas/tests/io/excel/test_readers.py @@ -150,9 +150,7 @@ def parser(self, *args, **kwargs): expected = expected_defaults[read_ext[1:]] assert result == expected - def test_usecols_int(self, read_ext, df_ref): - df_ref = df_ref.reindex(columns=["A", "B", "C"]) - + def test_usecols_int(self, read_ext): # usecols as int msg = "Passing an integer for `usecols`" with pytest.raises(ValueError, match=msg): @@ -1311,7 +1309,7 @@ def cd_and_set_engine(self, engine, datapath, monkeypatch): monkeypatch.chdir(datapath("io", "data", "excel")) monkeypatch.setattr(pd, "ExcelFile", func) - def test_engine_used(self, read_ext, engine, monkeypatch): + def test_engine_used(self, read_ext, engine): expected_defaults = { "xlsx": "openpyxl", "xlsm": "openpyxl", diff --git a/pandas/tests/io/parser/conftest.py b/pandas/tests/io/parser/conftest.py index 2070057aff10b..e98d23d12bbd0 100644 --- a/pandas/tests/io/parser/conftest.py +++ b/pandas/tests/io/parser/conftest.py @@ -12,6 +12,9 @@ ) import pandas._testing as tm +from pandas.io.parsers import readers +from pandas.io.parsers.arrow_parser_wrapper import ArrowParserWrapper + class BaseParser: engine: str | None = None @@ -101,7 +104,7 @@ def csv1(datapath): @pytest.fixture(params=_all_parsers, ids=_all_parser_ids) -def all_parsers(request): +def all_parsers(request, monkeypatch): """ Fixture all of the CSV parsers. """ @@ -109,10 +112,21 @@ def all_parsers(request): if parser.engine == "pyarrow": pytest.importorskip("pyarrow", VERSIONS["pyarrow"]) # Try setting num cpus to 1 to avoid hangs? + # Disable threads in CI environment to avoid timeouts import pyarrow pyarrow.set_cpu_count(1) - return parser + + class NoThreadArrowParserWrapper(ArrowParserWrapper): + def _get_pyarrow_options(self): + super()._get_pyarrow_options() + self.read_options["use_threads"] = False + + with monkeypatch.context() as m: + m.setattr(readers, "ArrowParserWrapper", NoThreadArrowParserWrapper) + yield parser + else: + yield parser @pytest.fixture(params=_c_parsers_only, ids=_c_parser_ids) diff --git a/pandas/tests/io/test_sql.py b/pandas/tests/io/test_sql.py index 741af4324c1a6..584308db3bae8 100644 --- a/pandas/tests/io/test_sql.py +++ b/pandas/tests/io/test_sql.py @@ -498,6 +498,7 @@ def sqlite_buildin_iris(sqlite_buildin, iris_path): all_connectable_iris = sqlalchemy_connectable_iris + ["sqlite_buildin_iris"] +@pytest.mark.db @pytest.mark.parametrize("conn", all_connectable) @pytest.mark.parametrize("method", [None, "multi"]) def test_to_sql(conn, method, test_frame1, request): @@ -508,6 +509,7 @@ def test_to_sql(conn, method, test_frame1, request): assert count_rows(conn, "test_frame") == len(test_frame1) +@pytest.mark.db @pytest.mark.parametrize("conn", all_connectable) @pytest.mark.parametrize("mode, num_row_coef", [("replace", 1), ("append", 2)]) def test_to_sql_exist(conn, mode, num_row_coef, test_frame1, request): @@ -519,6 +521,7 @@ def test_to_sql_exist(conn, mode, num_row_coef, test_frame1, request): assert count_rows(conn, "test_frame") == num_row_coef * len(test_frame1) +@pytest.mark.db @pytest.mark.parametrize("conn", all_connectable) def test_to_sql_exist_fail(conn, test_frame1, request): conn = request.getfixturevalue(conn) @@ -531,6 +534,7 @@ def test_to_sql_exist_fail(conn, test_frame1, request): pandasSQL.to_sql(test_frame1, "test_frame", if_exists="fail") +@pytest.mark.db @pytest.mark.parametrize("conn", all_connectable_iris) def test_read_iris(conn, request): conn = request.getfixturevalue(conn) @@ -539,6 +543,7 @@ def test_read_iris(conn, request): check_iris_frame(iris_frame) +@pytest.mark.db @pytest.mark.parametrize("conn", sqlalchemy_connectable) def test_to_sql_callable(conn, test_frame1, request): conn = request.getfixturevalue(conn) @@ -557,6 +562,7 @@ def sample(pd_table, conn, keys, data_iter): assert count_rows(conn, "test_frame") == len(test_frame1) +@pytest.mark.db @pytest.mark.parametrize("conn", mysql_connectable) def test_default_type_conversion(conn, request): conn = request.getfixturevalue(conn) @@ -575,6 +581,7 @@ def test_default_type_conversion(conn, request): assert issubclass(df.BoolColWithNull.dtype.type, np.floating) +@pytest.mark.db @pytest.mark.parametrize("conn", mysql_connectable) def test_read_procedure(conn, request): conn = request.getfixturevalue(conn) @@ -611,6 +618,7 @@ def test_read_procedure(conn, request): tm.assert_frame_equal(df, res2) +@pytest.mark.db @pytest.mark.parametrize("conn", postgresql_connectable) def test_copy_from_callable_insertion_method(conn, request): # GH 8953 diff --git a/pandas/tests/window/test_numba.py b/pandas/tests/window/test_numba.py index a9e38751c9a2f..36625d86873f6 100644 --- a/pandas/tests/window/test_numba.py +++ b/pandas/tests/window/test_numba.py @@ -1,6 +1,12 @@ +import os + import numpy as np import pytest +from pandas.compat import ( + is_platform_mac, + is_platform_windows, +) from pandas.errors import NumbaUtilError import pandas.util._test_decorators as td @@ -13,6 +19,15 @@ import pandas._testing as tm from pandas.core.util.numba_ import NUMBA_FUNC_CACHE +# TODO: Mark these as pytest.mark.single GH 44584 +pytestmark = pytest.mark.skipif( + os.environ.get("PANDAS_CI", "0") == "1" + and (is_platform_windows() or is_platform_mac()), + reason="On Azure CI, Windows can fail with " + "'Windows fatal exception: stack overflow' " + "and MacOS can timeout", +) + @pytest.fixture(params=["single", "table"]) def method(request): diff --git a/pandas/tests/window/test_online.py b/pandas/tests/window/test_online.py index 80cf1c55958ee..debf87bf6ade1 100644 --- a/pandas/tests/window/test_online.py +++ b/pandas/tests/window/test_online.py @@ -1,6 +1,12 @@ +import os + import numpy as np import pytest +from pandas.compat import ( + is_platform_mac, + is_platform_windows, +) import pandas.util._test_decorators as td from pandas import ( @@ -9,6 +15,15 @@ ) import pandas._testing as tm +# TODO: Mark these as pytest.mark.single GH 44584 +pytestmark = pytest.mark.skipif( + os.environ.get("PANDAS_CI", "0") == "1" + and (is_platform_windows() or is_platform_mac()), + reason="On Azure CI, Windows can fail with " + "'Windows fatal exception: stack overflow' " + "and MacOS can timeout", +) + @td.skip_if_no("numba") @pytest.mark.filterwarnings("ignore:\n") diff --git a/pandas/util/_test_decorators.py b/pandas/util/_test_decorators.py index 78ef335adf948..10322a25ffd18 100644 --- a/pandas/util/_test_decorators.py +++ b/pandas/util/_test_decorators.py @@ -266,7 +266,8 @@ def file_leak_context(): ContextManager analogue to check_file_leaks. """ psutil = safe_import("psutil") - if not psutil: + if not psutil or is_platform_windows(): + # Checking for file leaks can hang on Windows CI yield else: proc = psutil.Process() From b904b8818e77a62beec2f4ffeb6d95b1295c94da Mon Sep 17 00:00:00 2001 From: Matthew Roeschke Date: Sat, 29 Jan 2022 18:29:55 -0800 Subject: [PATCH 2/3] Revert pyarrow change and change todo format --- pandas/tests/io/parser/conftest.py | 22 +++++----------------- pandas/tests/window/test_numba.py | 2 +- pandas/tests/window/test_online.py | 2 +- 3 files changed, 7 insertions(+), 19 deletions(-) diff --git a/pandas/tests/io/parser/conftest.py b/pandas/tests/io/parser/conftest.py index e98d23d12bbd0..b2d2be362d0d3 100644 --- a/pandas/tests/io/parser/conftest.py +++ b/pandas/tests/io/parser/conftest.py @@ -12,9 +12,6 @@ ) import pandas._testing as tm -from pandas.io.parsers import readers -from pandas.io.parsers.arrow_parser_wrapper import ArrowParserWrapper - class BaseParser: engine: str | None = None @@ -104,29 +101,20 @@ def csv1(datapath): @pytest.fixture(params=_all_parsers, ids=_all_parser_ids) -def all_parsers(request, monkeypatch): +def all_parsers(request): """ Fixture all of the CSV parsers. """ parser = request.param() if parser.engine == "pyarrow": pytest.importorskip("pyarrow", VERSIONS["pyarrow"]) - # Try setting num cpus to 1 to avoid hangs? - # Disable threads in CI environment to avoid timeouts + # Try setting num cpus to 1 to avoid hangs on Azure MacOS/Windows builds + # or better yet find a way to disable threads + # TODO(GH#44584) pytest.mark.single these tests import pyarrow pyarrow.set_cpu_count(1) - - class NoThreadArrowParserWrapper(ArrowParserWrapper): - def _get_pyarrow_options(self): - super()._get_pyarrow_options() - self.read_options["use_threads"] = False - - with monkeypatch.context() as m: - m.setattr(readers, "ArrowParserWrapper", NoThreadArrowParserWrapper) - yield parser - else: - yield parser + return parser @pytest.fixture(params=_c_parsers_only, ids=_c_parser_ids) diff --git a/pandas/tests/window/test_numba.py b/pandas/tests/window/test_numba.py index 36625d86873f6..2c9ae3d70f218 100644 --- a/pandas/tests/window/test_numba.py +++ b/pandas/tests/window/test_numba.py @@ -19,7 +19,7 @@ import pandas._testing as tm from pandas.core.util.numba_ import NUMBA_FUNC_CACHE -# TODO: Mark these as pytest.mark.single GH 44584 +# TODO(GH#44584): Mark these as pytest.mark.single pytestmark = pytest.mark.skipif( os.environ.get("PANDAS_CI", "0") == "1" and (is_platform_windows() or is_platform_mac()), diff --git a/pandas/tests/window/test_online.py b/pandas/tests/window/test_online.py index debf87bf6ade1..543e5e4e545e0 100644 --- a/pandas/tests/window/test_online.py +++ b/pandas/tests/window/test_online.py @@ -15,7 +15,7 @@ ) import pandas._testing as tm -# TODO: Mark these as pytest.mark.single GH 44584 +# TODO(GH#44584): Mark these as pytest.mark.single pytestmark = pytest.mark.skipif( os.environ.get("PANDAS_CI", "0") == "1" and (is_platform_windows() or is_platform_mac()), From ca0b64211b37e5dd4bbaa4e0562c3b24fa29a9cc Mon Sep 17 00:00:00 2001 From: Matthew Roeschke Date: Sat, 29 Jan 2022 23:49:07 -0800 Subject: [PATCH 3/3] Remove -v --- ci/run_tests.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ci/run_tests.sh b/ci/run_tests.sh index 344982920273e..020a3ed7f265c 100755 --- a/ci/run_tests.sh +++ b/ci/run_tests.sh @@ -24,7 +24,7 @@ if [[ $(uname) == "Linux" && -z $DISPLAY ]]; then XVFB="xvfb-run " fi -PYTEST_CMD="${XVFB}pytest -v -r fEs -m \"$PATTERN\" -n $PYTEST_WORKERS --dist=loadfile $TEST_ARGS $COVERAGE $PYTEST_TARGET" +PYTEST_CMD="${XVFB}pytest -r fEs -m \"$PATTERN\" -n $PYTEST_WORKERS --dist=loadfile $TEST_ARGS $COVERAGE $PYTEST_TARGET" if [[ $(uname) != "Linux" && $(uname) != "Darwin" ]]; then PYTEST_CMD="$PYTEST_CMD --ignore=pandas/tests/plotting/"