Skip to content

Commit df9f7b1

Browse files
authored
Merge pull request #31 from getyourguide/change-docs-theme
docs: improved the API docs website
2 parents d62ce0b + 966ea5a commit df9f7b1

File tree

10 files changed

+382
-599
lines changed

10 files changed

+382
-599
lines changed

dataframe_expectations/expectations/aggregation/unique.py

Lines changed: 16 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -24,33 +24,30 @@
2424

2525
class ExpectationUniqueRows(DataFrameAggregationExpectation):
2626
"""
27-
Expectation that checks if there are no duplicate rows for the given column names. If columns list is empty, checks for duplicates across all columns.
27+
Expectation that checks if there are no duplicate rows for the given column names.
2828
29-
For example:
30-
For column_names ["col1", "col2"]
29+
If columns list is empty, checks for duplicates across all columns.
3130
32-
Given the following DataFrame:
31+
Example::
3332
34-
| col1 | col2 | col3 |
35-
|------|------|------|
36-
| 1 | 10 | 100 |
37-
| 2 | 20 | 100 |
38-
| 3 | 30 | 100 |
39-
| 1 | 20 | 100 |
33+
For column_names ["col1", "col2"], given a DataFrame with columns col1, col2, col3:
4034
41-
All rows are unique for columns ["col1", "col2"] and there will be no violations.
35+
- If all rows have unique combinations of col1 and col2 values, there are no violations
36+
- If any rows have identical col1 AND col2 values, those are violations
4237
43-
For the same columns_names and the following DataFrame:
38+
Example passing case (all unique)::
4439
45-
| col1 | col2 | col3 |
46-
|------|------|------|
47-
| 1 | 10 | 100 |
48-
| 2 | 20 | 100 |
49-
| 3 | 30 | 100 |
50-
| 1 | 10 | 100 |
40+
col1=1, col2=10
41+
col1=2, col2=20
42+
col1=3, col2=30
43+
col1=1, col2=20 # Different col2, so unique
5144
52-
There will be 1 violation because the first and last rows are duplicates for columns ["col1", "col2"].
45+
Example failing case (duplicate found)::
5346
47+
col1=1, col2=10
48+
col1=2, col2=20
49+
col1=3, col2=30
50+
col1=1, col2=10 # Duplicate of first row
5451
"""
5552

5653
def __init__(self, column_names: List[str], tags: Optional[List[str]] = None):

dataframe_expectations/suite.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -374,7 +374,8 @@ def validate(self, func: Optional[Callable] = None, *, allow_none: bool = False)
374374
by the decorated function. If validation fails, it raises
375375
DataFrameExpectationsSuiteFailure.
376376
377-
Example:
377+
Example::
378+
378379
runner = suite.build()
379380
380381
@runner.validate
@@ -439,7 +440,8 @@ class DataFrameExpectationsSuite:
439440
Use this class to add expectations, then call build() to create an
440441
immutable runner that can execute the expectations on DataFrames.
441442
442-
Example:
443+
Example::
444+
443445
suite = DataFrameExpectationsSuite(suite_name="user_validation")
444446
suite.expect_value_greater_than(
445447
column_name="age",

dataframe_expectations/suite.pyi

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,8 @@ class DataFrameExpectationsSuiteRunner:
118118
by the decorated function. If validation fails, it raises
119119
DataFrameExpectationsSuiteFailure.
120120
121-
Example:
121+
Example::
122+
122123
runner = suite.build()
123124
124125
@runner.validate
@@ -149,7 +150,8 @@ class DataFrameExpectationsSuite:
149150
Use this class to add expectations, then call build() to create an
150151
immutable runner that can execute the expectations on DataFrames.
151152
152-
Example:
153+
Example::
154+
153155
suite = DataFrameExpectationsSuite(suite_name="user_validation")
154156
suite.expect_value_greater_than(
155157
column_name="age",

docs/requirements.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
sphinx>=4.0.0
2-
sphinx-rtd-theme>=1.0.0
2+
sphinx-book-theme>=1.0.0
33
sphinx-autobuild>=2021.3.14

docs/source/_ext/expectations_autodoc.py

Lines changed: 46 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -168,7 +168,7 @@ def run(self) -> List[Node]:
168168
return nodes_list
169169

170170
def _generate_summary_table(self, expectations_by_category, method_details) -> List[Node]:
171-
"""Generate summary table nodes."""
171+
"""Generate summary as a two-level table"""
172172
nodes_list = []
173173

174174
# Add section with title and proper ID
@@ -180,13 +180,17 @@ def _generate_summary_table(self, expectations_by_category, method_details) -> L
180180

181181
# Create table
182182
table = nodes.table()
183+
table['classes'] = ['summary-table']
183184
tgroup = nodes.tgroup(cols=3)
184185
table += tgroup
185186

186187
# Add column specifications
187-
for width in [30, 25, 45]:
188-
colspec = nodes.colspec(colwidth=width)
189-
tgroup += colspec
188+
colspec1 = nodes.colspec(colwidth=25)
189+
colspec2 = nodes.colspec(colwidth=20)
190+
colspec3 = nodes.colspec(colwidth=55)
191+
tgroup += colspec1
192+
tgroup += colspec2
193+
tgroup += colspec3
190194

191195
# Add table head
192196
thead = nodes.thead()
@@ -197,48 +201,67 @@ def _generate_summary_table(self, expectations_by_category, method_details) -> L
197201

198202
for header in ["Category", "Subcategory", "Expectations"]:
199203
entry = nodes.entry()
204+
entry['classes'] = ['summary-table-header']
200205
row += entry
201-
entry += nodes.paragraph("", header)
206+
para = nodes.paragraph()
207+
para += nodes.Text(header)
208+
entry += para
202209

203210
# Add table body
204211
tbody = nodes.tbody()
205212
tgroup += tbody
206213

207214
for category in sorted(expectations_by_category.keys()):
208-
for subcategory in sorted(expectations_by_category[category].keys()):
209-
expectations = expectations_by_category[category][subcategory]
215+
subcategories = expectations_by_category[category]
216+
217+
for idx, subcategory in enumerate(sorted(subcategories.keys())):
218+
expectations = subcategories[subcategory]
210219

211220
row = nodes.row()
221+
row['classes'] = ['summary-table-row']
212222
tbody += row
213223

214-
# Category cell
224+
# Category cell (only show on first subcategory)
215225
entry = nodes.entry()
216-
row += entry
217-
entry += nodes.paragraph("", category)
226+
if idx == 0:
227+
entry['morerows'] = len(subcategories) - 1 # Span multiple rows
228+
entry['classes'] = ['summary-category-cell']
229+
para = nodes.paragraph()
230+
para += nodes.Text(f"{category} ({sum(len(subcategories[s]) for s in subcategories)})")
231+
entry += para
232+
row += entry
218233

219234
# Subcategory cell
220235
entry = nodes.entry()
236+
entry['classes'] = ['summary-subcategory-cell']
237+
para = nodes.paragraph()
238+
para += nodes.Text(f"{subcategory} ({len(expectations)})")
239+
entry += para
221240
row += entry
222-
entry += nodes.paragraph("", subcategory)
223241

224-
# Expectations cell
242+
# Expectations cell with badges
225243
entry = nodes.entry()
226-
row += entry
244+
entry['classes'] = ['summary-expectations-cell']
245+
246+
badges_container = nodes.container()
247+
badges_container['classes'] = ['expectation-badges']
227248

228-
exp_para = nodes.paragraph()
229-
for i, exp in enumerate(sorted(expectations)):
230-
if i > 0:
231-
exp_para += nodes.Text(", ")
249+
for exp in sorted(expectations):
250+
# Get description for tooltip
251+
details = method_details[exp]
252+
clean_docstring = clean_docstring_from_metadata(details["docstring"])
253+
description = clean_docstring.split('\n')[0] if clean_docstring else ""
232254

233-
# Create clickable link to the card using raw HTML
234-
raw_link = nodes.raw(
235-
f'<a href="#card-{exp}" class="expectation-link">{exp}</a>',
236-
f'<a href="#card-{exp}" class="expectation-link">{exp}</a>',
255+
# Create badge with link
256+
badge = nodes.raw(
257+
f'<a href="#card-{exp}" class="expectation-badge" title="{description}">{exp}</a>',
258+
f'<a href="#card-{exp}" class="expectation-badge" title="{description}">{exp}</a>',
237259
format='html'
238260
)
239-
exp_para += raw_link
261+
badges_container += badge
240262

241-
entry += exp_para
263+
entry += badges_container
264+
row += entry
242265

243266
summary_section += table
244267
nodes_list.append(summary_section)

0 commit comments

Comments
 (0)