1"""
2Testing that we work in the downstream packages
3"""
4import importlib
5import subprocess
6import sys
7
8import numpy as np  # noqa
9import pytest
10
11import pandas.util._test_decorators as td
12
13from pandas import DataFrame
14import pandas._testing as tm
15
16
17def import_module(name):
18    # we *only* want to skip if the module is truly not available
19    # and NOT just an actual import error because of pandas changes
20
21    try:
22        return importlib.import_module(name)
23    except ModuleNotFoundError:
24        pytest.skip(f"skipping as {name} not available")
25
26
27@pytest.fixture
28def df():
29    return DataFrame({"A": [1, 2, 3]})
30
31
32def test_dask(df):
33
34    toolz = import_module("toolz")  # noqa
35    dask = import_module("dask")  # noqa
36
37    import dask.dataframe as dd
38
39    ddf = dd.from_pandas(df, npartitions=3)
40    assert ddf.A is not None
41    assert ddf.compute() is not None
42
43
44def test_xarray(df):
45
46    xarray = import_module("xarray")  # noqa
47
48    assert df.to_xarray() is not None
49
50
51@td.skip_if_no("cftime")
52@td.skip_if_no("xarray", "0.10.4")
53def test_xarray_cftimeindex_nearest():
54    # https://github.com/pydata/xarray/issues/3751
55    import cftime
56    import xarray
57
58    times = xarray.cftime_range("0001", periods=2)
59    result = times.get_loc(cftime.DatetimeGregorian(2000, 1, 1), method="nearest")
60    expected = 1
61    assert result == expected
62
63
64def test_oo_optimizable():
65    # GH 21071
66    subprocess.check_call([sys.executable, "-OO", "-c", "import pandas"])
67
68
69@tm.network
70# Cython import warning
71@pytest.mark.filterwarnings("ignore:pandas.util.testing is deprecated")
72@pytest.mark.filterwarnings("ignore:can't:ImportWarning")
73@pytest.mark.filterwarnings(
74    # patsy needs to update their imports
75    "ignore:Using or importing the ABCs from 'collections:DeprecationWarning"
76)
77def test_statsmodels():
78
79    statsmodels = import_module("statsmodels")  # noqa
80    import statsmodels.api as sm
81    import statsmodels.formula.api as smf
82
83    df = sm.datasets.get_rdataset("Guerry", "HistData").data
84    smf.ols("Lottery ~ Literacy + np.log(Pop1831)", data=df).fit()
85
86
87# Cython import warning
88@pytest.mark.filterwarnings("ignore:can't:ImportWarning")
89def test_scikit_learn(df):
90
91    sklearn = import_module("sklearn")  # noqa
92    from sklearn import datasets, svm
93
94    digits = datasets.load_digits()
95    clf = svm.SVC(gamma=0.001, C=100.0)
96    clf.fit(digits.data[:-1], digits.target[:-1])
97    clf.predict(digits.data[-1:])
98
99
100# Cython import warning and traitlets
101@tm.network
102@pytest.mark.filterwarnings("ignore")
103def test_seaborn():
104
105    seaborn = import_module("seaborn")
106    tips = seaborn.load_dataset("tips")
107    seaborn.stripplot(x="day", y="total_bill", data=tips)
108
109
110def test_pandas_gbq(df):
111
112    pandas_gbq = import_module("pandas_gbq")  # noqa
113
114
115@pytest.mark.xfail(reason="0.8.1 tries to import urlencode from pd.io.common")
116@tm.network
117def test_pandas_datareader():
118
119    pandas_datareader = import_module("pandas_datareader")
120    pandas_datareader.DataReader("F", "quandl", "2017-01-01", "2017-02-01")
121
122
123# importing from pandas, Cython import warning
124@pytest.mark.filterwarnings("ignore:can't resolve:ImportWarning")
125def test_geopandas():
126
127    geopandas = import_module("geopandas")
128    fp = geopandas.datasets.get_path("naturalearth_lowres")
129    assert geopandas.read_file(fp) is not None
130
131
132# Cython import warning
133@pytest.mark.filterwarnings("ignore:can't resolve:ImportWarning")
134@pytest.mark.filterwarnings("ignore:RangeIndex.* is deprecated:DeprecationWarning")
135def test_pyarrow(df):
136
137    pyarrow = import_module("pyarrow")
138    table = pyarrow.Table.from_pandas(df)
139    result = table.to_pandas()
140    tm.assert_frame_equal(result, df)
141
142
143def test_missing_required_dependency():
144    # GH 23868
145    # To ensure proper isolation, we pass these flags
146    # -S : disable site-packages
147    # -s : disable user site-packages
148    # -E : disable PYTHON* env vars, especially PYTHONPATH
149    # https://github.com/MacPython/pandas-wheels/pull/50
150
151    pyexe = sys.executable.replace("\\", "/")
152
153    # We skip this test if pandas is installed as a site package. We first
154    # import the package normally and check the path to the module before
155    # executing the test which imports pandas with site packages disabled.
156    call = [pyexe, "-c", "import pandas;print(pandas.__file__)"]
157    output = subprocess.check_output(call).decode()
158    if "site-packages" in output:
159        pytest.skip("pandas installed as site package")
160
161    # This test will fail if pandas is installed as a site package. The flags
162    # prevent pandas being imported and the test will report Failed: DID NOT
163    # RAISE <class 'subprocess.CalledProcessError'>
164    call = [pyexe, "-sSE", "-c", "import pandas"]
165
166    msg = (
167        rf"Command '\['{pyexe}', '-sSE', '-c', 'import pandas'\]' "
168        "returned non-zero exit status 1."
169    )
170
171    with pytest.raises(subprocess.CalledProcessError, match=msg) as exc:
172        subprocess.check_output(call, stderr=subprocess.STDOUT)
173
174    output = exc.value.stdout.decode()
175    for name in ["numpy", "pytz", "dateutil"]:
176        assert name in output
177