Skip to content

Commit

Permalink
Limit HTML output
Browse files Browse the repository at this point in the history
  • Loading branch information
benjeffery authored and mergify[bot] committed Sep 25, 2024
1 parent e724f33 commit 36c6786
Show file tree
Hide file tree
Showing 3 changed files with 56 additions and 21 deletions.
3 changes: 3 additions & 0 deletions python/CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@
- Printing ``tskit.MetadataSchema(schema=None)`` now shows ``"Null_schema"`` rather
than ``None``, to avoid confusion (:user:`hyanwong`, :pr:`2720`)

- Limit output HTML when a tree sequence is displayed that has a large amount of metadata.
(:user:`benjeffery`, :pr:`2999`)

**Features**

- Add ``TreeSequence.extend_haplotypes`` method that extends ancestral haplotypes
Expand Down
9 changes: 9 additions & 0 deletions python/tests/test_highlevel.py
Original file line number Diff line number Diff line change
Expand Up @@ -2196,6 +2196,15 @@ def test_html_repr(self, ts):
for table in ts.tables.table_name_map:
assert f"<td>{table.capitalize()}</td>" in html

def test_html_repr_limit(self, ts_fixture):
tables = ts_fixture.tables
d = {n: n for n in range(50)}
d[0] = "N" * 200
tables.metadata = d
ts = tables.tree_sequence()
assert "... and 20 more" in ts._repr_html_()
assert "NN..." in ts._repr_html_()

@pytest.mark.parametrize("ts", get_example_tree_sequences())
def test_str(self, ts):
s = str(ts)
Expand Down
65 changes: 44 additions & 21 deletions python/tskit/util.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
import json
import numbers
import os
import textwrap
from typing import Union

import numpy as np
Expand Down Expand Up @@ -323,43 +324,65 @@ def naturalsize(value):
return (format_ + " %s") % ((base * bytes_ / unit), s)


def obj_to_collapsed_html(d, name=None, open_depth=0):
def obj_to_collapsed_html(d, name=None, open_depth=0, max_items=30, max_item_len=100):
"""
Recursively make an HTML representation of python objects.
:param str name: Name for this object
:param int open_depth: By default sub-sections are collapsed. If this number is
non-zero the first layers up to open_depth will be opened.
:param int max_items: Maximum number of items to display per collection
:return: The HTML as a string
:rtype: str
"""
opened = "open" if open_depth > 0 else ""
open_depth -= 1
name = str(name) + ":" if name is not None else ""
if type(d) is dict:
name = f"{str(name)}:" if name is not None else ""
if isinstance(d, dict):
items = list(d.items())
more = len(items) - max_items
display_items = items[:max_items] if more > 0 else items
inner_html = "".join(
f"{obj_to_collapsed_html(val, key, open_depth, max_items)}<br/>"
for key, val in display_items
)
if more > 0:
inner_html += f"... and {more} more"
return f"""
<div>
<span class="tskit-details-label">{name}</span>
<details {opened}>
<div>
<span class="tskit-details-label">{name}</span>
<details {opened}>
<summary>dict</summary>
{"".join(f"{obj_to_collapsed_html(val, key, open_depth)}<br/>"
for key, val in d.items())}
</details>
</div>
"""
elif type(d) is list:
{inner_html}
</details>
</div>
"""
elif isinstance(d, list):
items = d
more = len(items) - max_items
display_items = items[:max_items] if more > 0 else items
inner_html = "".join(
f"{obj_to_collapsed_html(val, None, open_depth, max_items)}<br/>"
for val in display_items
)
if more > 0:
inner_html += f"... and {more} more"
return f"""
<div>
<span class="tskit-details-label">{name}</span>
<details {opened}>
<div>
<span class="tskit-details-label">{name}</span>
<details {opened}>
<summary>list</summary>
{"".join(f"{obj_to_collapsed_html(val, None, open_depth)}<br/>"
for val in d)}
</details>
</div>
"""
{inner_html}
</details>
</div>
"""
else:
return f"{name} {d}"
d_str = str(d)
if len(d_str) > max_item_len:
d_str = d_str[:max_item_len] + "..."
d_str = textwrap.fill(d_str, width=30)
d_str = d_str.replace("\n", "<br/>")
return f"{name} {d_str}"


def truncate_string_end(string, length):
Expand Down

0 comments on commit 36c6786

Please sign in to comment.