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 @@ -14,6 +14,8 @@ v0.6
- Added tabular regression example. :pr: `254` by `Thomas Lazarus`
adrinjalali marked this conversation as resolved.
Show resolved Hide resolved
- All public ``scipy.special`` ufuncs (Universal Functions) are trusted by default
by :func:`.io.load`. :pr:`295` by :user:`Omar Arab Oghli <omar-araboghli>`.
- 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 @@ -1315,3 +1315,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
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
"""
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:
"""Create a table of contents for the model card.
lazarust marked this conversation as resolved.
Show resolved Hide resolved
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
"""
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 @@ -1593,3 +1593,50 @@ def test_visibility_with_card_save(self, card):
"Jane Doe"
)
assert loaded.strip() == expected


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)