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 = """ %(lines)s
a b
""" 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( """ idxab 01b 12c 23a 34d 45e """ ).strip() in htmlstr_windx ) assert ( "realidxab" in htmlstr_windx_named ) assert "ab" 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")