Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ENH Adds ability to create table of contents #305

Merged
merged 14 commits into from
Mar 13, 2023
2 changes: 2 additions & 0 deletions docs/changes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ v0.6
by :func:`.io.load`. :pr:`295` by :user:`Omar Arab Oghli <omar-araboghli>`.
- Add a new function :func:`skops.card.Card.add_metric_frame` to help users
add metrics to their model cards. :pr:`298` by :user:`Thomas Lazarus <lazarust>`
- Add :func:`.Card.create_toc` to create a table of contents for the model card in
markdown format. :pr:`305` by :user:`Thomas Lazarus <lazarust>`.
- Add example of using model card without the skops template. :pr:`291` by
`Benjamin Bossan`_.
- Fix: skops persistence now also works with many functions from the
Expand Down
56 changes: 56 additions & 0 deletions skops/card/_model_card.py
Original file line number Diff line number Diff line change
Expand Up @@ -1442,3 +1442,59 @@ def render(self) -> str:
sections inserted.
"""
return "\n".join(self._generate_card())

def _iterate_key_section_content(
adrinjalali marked this conversation as resolved.
Show resolved Hide resolved
self,
data: dict[str, Section],
level: int = 0,
):
"""Iterate through the key sections and yield the title and level.

Parameters
----------
data : dict[str, Section]
The card data to iterate through. This is usually the sections and subsections.

level : int, optional
The level of the section, by default 0. This keeps track of subsections.

Returns
-------
table_of_contents : str
"""
for key, val in data.items():
lazarust marked this conversation as resolved.
Show resolved Hide resolved
if not getattr(val, "visible", True):
continue
lazarust marked this conversation as resolved.
Show resolved Hide resolved

title = val.title
yield title, level

if val.subsections:
yield from self._iterate_key_section_content(
val.subsections,
level=level + 1,
)

def get_toc(self) -> str:
"""Get the table of contents for the model card.

lazarust marked this conversation as resolved.
Show resolved Hide resolved
Returns
-------
toc : str
The table of contents for the model card formatted as a markdown string.
lazarust marked this conversation as resolved.
Show resolved Hide resolved
Example:
- Model description
- Intended uses & limitations
- Training Procedure
- Hyperparameters
- Model Plot
- Evaluation Results
- How to Get Started with the Model
- Model Card Authors
- Model Card Contact
"""
lazarust marked this conversation as resolved.
Show resolved Hide resolved
sections = []
for title, level in self._iterate_key_section_content(self._data):
sections.append(f"{' ' * level}- {title}")

return "\n".join(sections)
47 changes: 47 additions & 0 deletions skops/card/tests/test_card.py
Original file line number Diff line number Diff line change
Expand Up @@ -1777,3 +1777,50 @@ def test_metric_table_with_description(self, card: Card, metric_frame):
" |\n| 0.4 |\n| 0.5 |\n\n</details>"
)
assert expected_table == actual_table


class TestCardTableOfContents:
@pytest.fixture
def card(self):
model = LinearRegression()
card = Card(model=model)
card.add_model_plot()
card.add_hyperparams()
card.add_metrics(accuracy=0.1)
card.add_get_started_code()
return card

def test_toc(self, card):
toc = card.get_toc()
exptected_toc = [
"- Model description",
" - Intended uses & limitations",
" - Training Procedure",
" - Hyperparameters",
" - Model Plot",
" - Evaluation Results",
"- How to Get Started with the Model",
"- Model Card Authors",
"- Model Card Contact",
"- Citation",
]

assert toc == "\n".join(exptected_toc)

def test_toc_with_invisible_section(self, card):
section = card.select("Citation")
section.visible = False
toc = card.get_toc()
exptected_toc = [
"- Model description",
" - Intended uses & limitations",
" - Training Procedure",
" - Hyperparameters",
" - Model Plot",
" - Evaluation Results",
"- How to Get Started with the Model",
"- Model Card Authors",
"- Model Card Contact",
]

assert toc == "\n".join(exptected_toc)