import textwrap
from os.path import abspath, dirname, join
import pytest
from astropy import extern
from astropy.coordinates import SkyCoord
from astropy.table.table import Table
from astropy.time import Time
from astropy.utils.compat.optional_deps import (
HAS_BLEACH,
HAS_IPYDATAGRID,
HAS_IPYTHON,
HAS_PANDAS,
)
from astropy.utils.exceptions import AstropyDeprecationWarning
from astropy.utils.misc import _NOT_OVERWRITING_MSG_MATCH
EXTERN_DIR = abspath(join(dirname(extern.__file__), "jquery", "data"))
JQUERY_MIN_JS = "jquery-3.6.0.min.js"
REFERENCE = """
"""
TPL = " \n {0} \n {1} \n "
def format_lines(col1, col2):
col1_format = getattr(col1.info, "default_format", lambda x: x)
col2_format = getattr(col2.info, "default_format", lambda x: x)
return "\n".join(
TPL.format(col1_format(v1), col2_format(v2)) for v1, v2 in zip(col1, col2)
)
def test_write_jsviewer_default(tmp_path):
t = Table()
t["a"] = [1, 2, 3, 4, 5]
t["b"] = ["a", "b", "c", "d", "e"]
t["a"].unit = "m"
tmpfile = tmp_path / "test.html"
t.write(tmpfile, format="jsviewer")
ref = REFERENCE % dict(
lines=format_lines(t["a"], t["b"]),
table_class="display compact",
table_id=f"table{id(t)}",
length="50",
display_length="10, 25, 50, 100, 500, 1000",
datatables_css_url=(
"https://cdn.datatables.net/2.1.8/css/dataTables.dataTables.min.css"
),
datatables_js_url=("https://cdn.datatables.net/2.1.8/js/dataTables.min.js"),
jquery_url="https://code.jquery.com/" + JQUERY_MIN_JS,
)
with open(tmpfile) as f:
assert f.read().strip() == ref.strip()
def test_write_jsviewer_overwrite(tmp_path):
t = Table()
t["a"] = [1, 2, 3, 4, 5]
t["b"] = ["a", "b", "c", "d", "e"]
t["a"].unit = "m"
tmpfile = tmp_path / "test.html"
# normal write
t.write(tmpfile, format="jsviewer")
# errors on overwrite
with pytest.raises(OSError, match=_NOT_OVERWRITING_MSG_MATCH):
t.write(tmpfile, format="jsviewer")
# unless specified
t.write(tmpfile, format="jsviewer", overwrite=True)
@pytest.mark.parametrize(
"mixin",
[
Time(["J2000", "J2001"]),
Time([50000.0, 50001.0001], format="mjd"),
SkyCoord(ra=[100.0, 110.0], dec=[-10.0, 10.0], unit="deg"),
],
)
def test_write_jsviewer_mixin(tmp_path, mixin):
t = Table()
t["a"] = [1, 2]
t["b"] = mixin
t["a"].unit = "m"
tmpfile = tmp_path / "test.html"
t.write(tmpfile, format="jsviewer")
ref = REFERENCE % dict(
lines=format_lines(t["a"], t["b"]),
table_class="display compact",
table_id=f"table{id(t)}",
length="50",
display_length="10, 25, 50, 100, 500, 1000",
datatables_css_url=(
"https://cdn.datatables.net/2.1.8/css/dataTables.dataTables.min.css"
),
datatables_js_url=("https://cdn.datatables.net/2.1.8/js/dataTables.min.js"),
jquery_url="https://code.jquery.com/" + JQUERY_MIN_JS,
)
with open(tmpfile) as f:
assert f.read().strip() == ref.strip()
@pytest.mark.skipif(not HAS_BLEACH, reason="requires bleach")
def test_write_jsviewer_options(tmp_path):
t = Table()
t["a"] = [1, 2, 3, 4, 5]
t["b"] = ["a ", "b", "c", "d", "e"]
t["a"].unit = "m"
tmpfile = tmp_path / "test.html"
t.write(
tmpfile,
format="jsviewer",
table_id="test",
max_lines=3,
jskwargs={"display_length": 5},
table_class="display hover",
htmldict=dict(raw_html_cols="b"),
)
ref = REFERENCE % dict(
lines=format_lines(t["a"][:3], t["b"][:3]),
table_class="display hover",
table_id="test",
length="5",
display_length="5, 10, 25, 50, 100, 500, 1000",
datatables_css_url=(
"https://cdn.datatables.net/2.1.8/css/dataTables.dataTables.min.css"
),
datatables_js_url=("https://cdn.datatables.net/2.1.8/js/dataTables.min.js"),
jquery_url="https://code.jquery.com/" + JQUERY_MIN_JS,
)
with open(tmpfile) as f:
assert f.read().strip() == ref.strip()
def test_write_jsviewer_local(tmp_path):
t = Table()
t["a"] = [1, 2, 3, 4, 5]
t["b"] = ["a", "b", "c", "d", "e"]
t["a"].unit = "m"
tmpfile = tmp_path / "test.html"
with pytest.warns(AstropyDeprecationWarning, match="use_local_files is deprecated"):
t.write(
tmpfile,
format="jsviewer",
table_id="test",
jskwargs={"use_local_files": True},
)
ref = REFERENCE % dict(
lines=format_lines(t["a"], t["b"]),
table_class="display compact",
table_id="test",
length="50",
display_length="10, 25, 50, 100, 500, 1000",
datatables_css_url="file://" + join(EXTERN_DIR, "css", "datatables.css"),
datatables_js_url="file://" + join(EXTERN_DIR, "js", "datatables.min.js"),
jquery_url="file://" + join(EXTERN_DIR, "js", JQUERY_MIN_JS),
)
with open(tmpfile) as f:
assert f.read().strip() == ref.strip()
@pytest.mark.skipif(not HAS_IPYTHON, reason="requires IPython")
def test_show_in_notebook_classic():
t = Table()
t["a"] = [1, 2, 3, 4, 5]
t["b"] = ["b", "c", "a", "d", "e"]
with pytest.warns(AstropyDeprecationWarning):
htmlstr_windx = t.show_in_notebook(
backend="classic"
).data # should default to 'idx'
htmlstr_windx_named = t.show_in_notebook(
backend="classic", show_row_index="realidx"
).data
htmlstr_woindx = t.show_in_notebook(
backend="classic", show_row_index=False
).data
assert (
textwrap.dedent(
"""
idx a b
0 1 b
1 2 c
2 3 a
3 4 d
4 5 e
"""
).strip()
in htmlstr_windx
)
assert (
"realidx a b "
in htmlstr_windx_named
)
assert "a b " in htmlstr_woindx
@pytest.mark.skipif(
not HAS_IPYDATAGRID or not HAS_PANDAS, reason="requires ipydatagrid and pandas"
)
# https://github.com/bqplot/bqplot/issues/1624 and such
@pytest.mark.filterwarnings(r"ignore:((.|\n)*)traitlets((.|\n)*):DeprecationWarning")
def test_show_in_notebook_ipydatagrid():
from ipydatagrid import DataGrid
t = Table()
dg = t.show_in_notebook()
assert isinstance(dg, DataGrid)
def test_show_in_notebook_invalid_backend():
t = Table()
with pytest.raises(NotImplementedError, match=".* backend is not supported"):
t.show_in_notebook(backend="foo")