Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit c69a4c8

Browse files
authored
improve: parse google-style attributes in docstrings (marimo-team#3247)
Also, show examples right after summary, then args, attrs, ... I noticed that some (but not all) of the attributes sections had been converted to google-style and weren't rendering properly. This change fixes that.
1 parent fe38c85 commit c69a4c8

File tree

8 files changed

+100
-44
lines changed

8 files changed

+100
-44
lines changed

docs/api/inputs/dates.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
## Single date
44

5+
/// marimo-embed
6+
57
```python
68
@app.cell
79
def __():
@@ -15,6 +17,8 @@
1517

1618
```
1719

20+
///
21+
1822
::: marimo.ui.date
1923
:members:
2024

@@ -37,6 +41,8 @@
3741

3842
## Date range
3943

44+
/// marimo-embed
45+
4046
```python
4147
@app.cell
4248
def __():
@@ -49,5 +55,7 @@
4955
return
5056
```
5157

58+
///
59+
5260
::: marimo.ui.date_range
5361
:members:

marimo/_plugins/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
# Copyright 2024 Marimo. All rights reserved.
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
# Copyright 2024 Marimo. All rights reserved.
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
# Copyright 2024 Marimo. All rights reserved.

marimo/_utils/docs.py

Lines changed: 54 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
# Copyright 2024 Marimo. All rights reserved.
12
import re
23
from textwrap import dedent
34

@@ -25,14 +26,39 @@ def google_docstring_to_markdown(docstring: str) -> str:
2526
lines = docstring.strip().splitlines()
2627
parsed_lines: list[str] = []
2728
arg_table: list[tuple[str, str, str]] = []
29+
attribute_table: list[tuple[str, str, str]] = []
2830
returns_table: list[tuple[str, str]] = []
2931
raises_table: list[tuple[str, str]] = []
3032
in_args = False
33+
in_attributes = False
3134
in_returns = False
3235
in_raises = False
3336
in_examples = False
3437
examples_lines: list[str] = []
3538

39+
def _handle_arg_or_attribute(
40+
table: list[tuple[str, str, str]], stripped: str
41+
) -> None:
42+
# Typically: " arg_name (arg_type): description"
43+
match = re.match(r"^(\w+)\s*\(([^)]+)\):\s*(.*)", stripped)
44+
if match:
45+
arg_name, arg_type, description = match.groups()
46+
table.append((arg_name, arg_type, description.strip()))
47+
else:
48+
# Fallback to " arg_name: description"
49+
match = re.match(r"^(\w+)\s*:\s*(.*)", stripped)
50+
if match:
51+
arg_name, description = match.groups()
52+
table.append((arg_name, "", description.strip()))
53+
else:
54+
# Possibly just an indented line continuing the description
55+
if table:
56+
table[-1] = (
57+
table[-1][0],
58+
table[-1][1],
59+
table[-1][2] + " " + stripped.strip(),
60+
)
61+
3662
# We'll store a simple summary until we see "Args:" or "Returns:" or "Raises:"
3763
for line in lines:
3864
# Only strip the first 4 spaces
@@ -44,24 +70,35 @@ def google_docstring_to_markdown(docstring: str) -> str:
4470
# Check for control keywords
4571
if re.match(r"^Args:\s*$", stripped):
4672
in_args = True
73+
in_attributes = False
74+
in_returns = False
75+
in_raises = False
76+
in_examples = False
77+
continue
78+
elif re.match(r"^Attributes:\s*$", stripped):
79+
in_args = False
80+
in_attributes = True
4781
in_returns = False
4882
in_raises = False
4983
in_examples = False
5084
continue
5185
elif re.match(r"^Returns?:\s*$", stripped):
5286
in_args = False
87+
in_attributes = False
5388
in_returns = True
5489
in_raises = False
5590
in_examples = False
5691
continue
5792
elif re.match(r"^Raises:\s*$", stripped):
5893
in_args = False
94+
in_attributes = False
5995
in_returns = False
6096
in_raises = True
6197
in_examples = False
6298
continue
6399
elif re.match(r"^Examples?:\s*$", stripped):
64100
in_args = False
101+
in_attributes = False
65102
in_returns = False
66103
in_raises = False
67104
in_examples = True
@@ -74,25 +111,12 @@ def google_docstring_to_markdown(docstring: str) -> str:
74111

75112
# If within Args:
76113
if in_args:
77-
# Typically: " arg_name (arg_type): description"
78-
match = re.match(r"^(\w+)\s*\(([^)]+)\):\s*(.*)", stripped)
79-
if match:
80-
arg_name, arg_type, description = match.groups()
81-
arg_table.append((arg_name, arg_type, description.strip()))
82-
else:
83-
# Fallback to " arg_name: description"
84-
match = re.match(r"^(\w+)\s*:\s*(.*)", stripped)
85-
if match:
86-
arg_name, description = match.groups()
87-
arg_table.append((arg_name, "", description.strip()))
88-
else:
89-
# Possibly just an indented line continuing the description
90-
if arg_table:
91-
arg_table[-1] = (
92-
arg_table[-1][0],
93-
arg_table[-1][1],
94-
arg_table[-1][2] + " " + stripped.strip(),
95-
)
114+
_handle_arg_or_attribute(arg_table, stripped)
115+
continue
116+
117+
# If within Attributes:
118+
if in_attributes:
119+
_handle_arg_or_attribute(attribute_table, stripped)
96120
continue
97121

98122
# If within Returns:
@@ -138,13 +162,24 @@ def google_docstring_to_markdown(docstring: str) -> str:
138162
output.append("# Summary")
139163
output.append("\n".join(parsed_lines).strip())
140164

165+
if examples_lines:
166+
output.append("\n# Examples")
167+
output.append("\n".join(examples_lines))
168+
141169
if arg_table:
142170
output.append("\n# Arguments")
143171
output.append("| Parameter | Type | Description |")
144172
output.append("|-----------|------|-------------|")
145173
for arg_name, arg_type, desc in arg_table:
146174
output.append(f"| `{arg_name}` | `{arg_type}` | {desc.strip()} |")
147175

176+
if attribute_table:
177+
output.append("\n# Attributes")
178+
output.append("| Attribute | Type | Description |")
179+
output.append("|-----------|------|-------------|")
180+
for arg_name, arg_type, desc in attribute_table:
181+
output.append(f"| `{arg_name}` | `{arg_type}` | {desc.strip()} |")
182+
148183
if returns_table:
149184
output.append("\n# Returns")
150185
output.append("| Type | Description |")
@@ -157,8 +192,4 @@ def google_docstring_to_markdown(docstring: str) -> str:
157192
for err_type, explanation in raises_table:
158193
output.append(f"- **{err_type}**: {explanation.strip()}")
159194

160-
if examples_lines:
161-
output.append("\n# Examples")
162-
output.append("\n".join(examples_lines))
163-
164195
return "\n".join(output)

tests/_utils/snapshots/docstring_complex.txt

Lines changed: 15 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2,20 +2,6 @@
22
Stack items vertically, in a column.
33
Combine with `hstack` to build a grid of items.
44

5-
# Arguments
6-
| Parameter | Type | Description |
7-
|-----------|------|-------------|
8-
| `items` | `Sequence[object]` | A list of items. |
9-
| `align` | `Literal["start", "end", "center", "stretch"], optional` | Align items horizontally: start, end, center, or stretch. |
10-
| `justify` | `Literal["start", "center", "end", "space-between", "space-around"]` | Justify items vertically: start, center, end, space-between, or space-around. Defaults to "start". |
11-
| `gap` | `float, optional` | Gap between items as a float in rem. 1rem is 16px by default. Defaults to 0.5. |
12-
| `heights` | `Union[Literal["equal"], Sequence[float]], optional` | "equal" to give items equal height; or a list of relative heights with same length as `items`, eg, [1, 2] means the second item is twice as tall as the first; or None for a sensible default. |
13-
14-
# Returns
15-
| Type | Description |
16-
|------|-------------|
17-
| `Html` | An Html object. |
18-
195
# Examples
206
Build a column of items:
217
```python
@@ -32,3 +18,18 @@ mo.vstack(
3218
]
3319
)
3420
```
21+
22+
23+
# Arguments
24+
| Parameter | Type | Description |
25+
|-----------|------|-------------|
26+
| `items` | `Sequence[object]` | A list of items. |
27+
| `align` | `Literal["start", "end", "center", "stretch"], optional` | Align items horizontally: start, end, center, or stretch. |
28+
| `justify` | `Literal["start", "center", "end", "space-between", "space-around"]` | Justify items vertically: start, center, end, space-between, or space-around. Defaults to "start". |
29+
| `gap` | `float, optional` | Gap between items as a float in rem. 1rem is 16px by default. Defaults to 0.5. |
30+
| `heights` | `Union[Literal["equal"], Sequence[float]], optional` | "equal" to give items equal height; or a list of relative heights with same length as `items`, eg, [1, 2] means the second item is twice as tall as the first; or None for a sensible default. |
31+
32+
# Returns
33+
| Type | Description |
34+
|------|-------------|
35+
| `Html` | An Html object. |
Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,28 @@
11
# Summary
22
This is the summary.
33

4+
# Examples
5+
```python
6+
print('Hello, world!')
7+
print(foo, bar)
8+
```
9+
410
# Arguments
511
| Parameter | Type | Description |
612
|-----------|------|-------------|
713
| `foo` | `str` | Lorem ipsum |
814
| `bar` | `int` | Dolor sit amet |
915

16+
# Attributes
17+
| Attribute | Type | Description |
18+
|-----------|------|-------------|
19+
| `baz` | `str` | Lorem ipsum |
20+
| `boo` | `int` | Dolor sit amet |
21+
1022
# Returns
1123
| Type | Description |
1224
|------|-------------|
1325
| `bool` | Return description |
1426

1527
# Raises
16-
- **ValueError**: Something about the value
17-
18-
# Examples
19-
```python
20-
print('Hello, world!')
21-
print(foo, bar)
22-
```
28+
- **ValueError**: Something about the value

tests/_utils/test_docs.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,10 @@ def test_google_docstring_to_markdown_summary():
1111
foo (str): Lorem ipsum
1212
bar (int): Dolor sit amet
1313
14+
Attributes:
15+
baz (str): Lorem ipsum
16+
boo (int): Dolor sit amet
17+
1418
Returns:
1519
bool: Return description
1620
@@ -32,6 +36,9 @@ def test_google_docstring_to_markdown_summary():
3236
"# Arguments",
3337
"`foo`",
3438
"`bar`",
39+
"# Attributes",
40+
"`baz`",
41+
"`boo`",
3542
"# Returns",
3643
"`bool`",
3744
"# Raises",

0 commit comments

Comments
 (0)