|
6 | 6 | import duckdb |
7 | 7 | import warnings |
8 | 8 | from importlib import import_module |
| 9 | +import sys |
9 | 10 |
|
10 | 11 | try: |
11 | 12 | # need to ignore warnings that might be thrown deep inside pandas's import tree (from dateutil in this case) |
12 | | - warnings.simplefilter(action='ignore', category=DeprecationWarning) |
13 | | - pandas = import_module('pandas') |
| 13 | + warnings.simplefilter(action="ignore", category=DeprecationWarning) |
| 14 | + pandas = import_module("pandas") |
14 | 15 | warnings.resetwarnings() |
15 | 16 |
|
16 | | - pyarrow_dtype = getattr(pandas, 'ArrowDtype', None) |
| 17 | + pyarrow_dtype = getattr(pandas, "ArrowDtype", None) |
17 | 18 | except ImportError: |
18 | 19 | pandas = None |
19 | 20 | pyarrow_dtype = None |
20 | 21 |
|
| 22 | + # Only install mock after we've failed to import pandas for conftest.py |
| 23 | + class MockPandas: |
| 24 | + def __getattr__(self, name): |
| 25 | + pytest.skip("pandas not available", allow_module_level=True) |
| 26 | + |
| 27 | + sys.modules["pandas"] = MockPandas() |
| 28 | + sys.modules["pandas.testing"] = MockPandas() |
| 29 | + sys.modules["pandas._testing"] = MockPandas() |
| 30 | + |
21 | 31 | # Check if pandas has arrow dtypes enabled |
22 | | -try: |
23 | | - from pandas.compat import pa_version_under7p0 |
| 32 | +if pandas is not None: |
| 33 | + try: |
| 34 | + from pandas.compat import pa_version_under7p0 |
24 | 35 |
|
25 | | - pyarrow_dtypes_enabled = not pa_version_under7p0 |
26 | | -except ImportError: |
| 36 | + pyarrow_dtypes_enabled = not pa_version_under7p0 |
| 37 | + except (ImportError, AttributeError): |
| 38 | + pyarrow_dtypes_enabled = False |
| 39 | +else: |
27 | 40 | pyarrow_dtypes_enabled = False |
28 | 41 |
|
29 | 42 |
|
30 | 43 | def import_pandas(): |
31 | 44 | if pandas: |
32 | 45 | return pandas |
33 | 46 | else: |
34 | | - pytest.skip("Couldn't import pandas") |
| 47 | + pytest.skip("Couldn't import pandas", allow_module_level=True) |
35 | 48 |
|
36 | 49 |
|
37 | 50 | # https://docs.pytest.org/en/latest/example/simple.html#control-skipping-of-tests-according-to-command-line-option |
38 | 51 | # https://stackoverflow.com/a/47700320 |
39 | 52 | def pytest_addoption(parser): |
40 | 53 | parser.addoption("--skiplist", action="append", nargs="+", type=str, help="skip listed tests") |
41 | 54 |
|
| 55 | +@pytest.hookimpl(hookwrapper=True) |
| 56 | +def pytest_runtest_call(item): |
| 57 | + """Convert pandas requirement exceptions to skips""" |
| 58 | + outcome = yield |
| 59 | + try: |
| 60 | + outcome.get_result() |
| 61 | + except Exception as e: |
| 62 | + if "'pandas' is required for this operation but it was not installed" in str(e): |
| 63 | + pytest.skip("pandas not available - test requires pandas functionality") |
| 64 | + |
| 65 | + |
42 | 66 |
|
43 | 67 | def pytest_collection_modifyitems(config, items): |
44 | 68 | tests_to_skip = config.getoption("--skiplist") |
|
0 commit comments