Skip to content

Commit a2f4ea9

Browse files
AlexTorxcmarquchrisjsewell
authored
👌 Improve parsing of multiline docstrings (#15)
Co-authored-by: Colin Marquardt <cmarqu42@gmail.com> Co-authored-by: Chris Sewell <chrisj_sewell@hotmail.com>
1 parent db7df22 commit a2f4ea9

File tree

4 files changed

+244
-1
lines changed

4 files changed

+244
-1
lines changed

‎sphinx_sqlalchemy/main.py

+6-1
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77

88
# from docutils.parsers.rst import directives
99
from sphinx.application import Sphinx
10+
from sphinx.util.docstrings import prepare_docstring
1011
from sphinx.util.docutils import SphinxDirective
1112
from sqlalchemy import Column, Constraint, inspect
1213
from sqlalchemy.orm.mapper import Mapper
@@ -97,8 +98,12 @@ def add_content(self, mapper: Mapper, definition: nodes.definition) -> None:
9798

9899
# class documentation
99100
if mapper.class_.__doc__:
101+
docstring_lines = prepare_docstring(
102+
mapper.class_.__doc__, self.state.document.settings.tab_width
103+
)
104+
100105
self.state.nested_parse(
101-
StringList(mapper.class_.__doc__.splitlines()),
106+
StringList(docstring_lines),
102107
self.content_offset,
103108
definition,
104109
)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,165 @@
1+
# serializer version: 1
2+
# name: test_multiline_docstring_d212
3+
'''
4+
<document source="<src>/index.rst">
5+
<definition_list classes="simple sqla">
6+
<definition_list_item>
7+
<term>
8+
module2.TestUserMultilineDocstringD212
9+
(
10+
<emphasis>
11+
dbusers_d212
12+
)
13+
<definition>
14+
<paragraph>
15+
A
16+
<literal>
17+
user
18+
.
19+
<paragraph>
20+
The user has a multi-line docstring:
21+
<literal_block xml:space="preserve">
22+
This is an indented code block
23+
<paragraph>
24+
This is the last line of the docstring.
25+
<rubric>
26+
Columns:
27+
<table align="left" classes="colwidths-auto">
28+
<tgroup cols="3">
29+
<colspec>
30+
<colspec>
31+
<colspec>
32+
<tbody>
33+
<row>
34+
<entry>
35+
<paragraph>
36+
<emphasis>
37+
pk*
38+
<entry>
39+
<paragraph>
40+
INTEGER
41+
<entry>
42+
<paragraph>
43+
<row>
44+
<entry>
45+
<paragraph>
46+
first_name
47+
<entry>
48+
<paragraph>
49+
VARCHAR?
50+
<entry>
51+
<paragraph>
52+
The name of the user.
53+
<row>
54+
<entry>
55+
<paragraph>
56+
last_name
57+
<entry>
58+
<paragraph>
59+
VARCHAR(255)?
60+
<entry>
61+
<paragraph>
62+
The surname of the user.
63+
<row>
64+
<entry>
65+
<paragraph>
66+
dob
67+
<entry>
68+
<paragraph>
69+
DATE
70+
<entry>
71+
<paragraph>
72+
The date of birth.
73+
<rubric>
74+
Constraints:
75+
<bullet_list>
76+
<list_item>
77+
<paragraph>
78+
PRIMARY KEY (pk)
79+
<list_item>
80+
<paragraph>
81+
UNIQUE (first_name, last_name)
82+
'''
83+
# ---
84+
# name: test_multiline_docstring_d213
85+
'''
86+
<document source="<src>/index.rst">
87+
<definition_list classes="simple sqla">
88+
<definition_list_item>
89+
<term>
90+
module2.TestUserMultilineDocstringD213
91+
(
92+
<emphasis>
93+
dbusers_d213
94+
)
95+
<definition>
96+
<paragraph>
97+
A
98+
<literal>
99+
user
100+
.
101+
<paragraph>
102+
The user has a multi-line docstring:
103+
<literal_block xml:space="preserve">
104+
This is an indented code block
105+
<paragraph>
106+
This is the last line of the docstring.
107+
<rubric>
108+
Columns:
109+
<table align="left" classes="colwidths-auto">
110+
<tgroup cols="3">
111+
<colspec>
112+
<colspec>
113+
<colspec>
114+
<tbody>
115+
<row>
116+
<entry>
117+
<paragraph>
118+
<emphasis>
119+
pk*
120+
<entry>
121+
<paragraph>
122+
INTEGER
123+
<entry>
124+
<paragraph>
125+
<row>
126+
<entry>
127+
<paragraph>
128+
first_name
129+
<entry>
130+
<paragraph>
131+
VARCHAR?
132+
<entry>
133+
<paragraph>
134+
The name of the user.
135+
<row>
136+
<entry>
137+
<paragraph>
138+
last_name
139+
<entry>
140+
<paragraph>
141+
VARCHAR(255)?
142+
<entry>
143+
<paragraph>
144+
The surname of the user.
145+
<row>
146+
<entry>
147+
<paragraph>
148+
dob
149+
<entry>
150+
<paragraph>
151+
DATE
152+
<entry>
153+
<paragraph>
154+
The date of birth.
155+
<rubric>
156+
Constraints:
157+
<bullet_list>
158+
<list_item>
159+
<paragraph>
160+
PRIMARY KEY (pk)
161+
<list_item>
162+
<paragraph>
163+
UNIQUE (first_name, last_name)
164+
'''
165+
# ---

‎tests/modules/module2.py

+40
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
from sqlalchemy import Column, UniqueConstraint, orm, types
2+
3+
Base = orm.declarative_base()
4+
5+
6+
class TestUserMultilineDocstringD212(Base):
7+
"""
8+
A ``user``.
9+
10+
The user has a multi-line docstring::
11+
12+
This is an indented code block
13+
14+
This is the last line of the docstring.
15+
"""
16+
17+
__tablename__ = "dbusers_d212"
18+
__table_args__ = (UniqueConstraint("first_name", "last_name"),)
19+
pk = Column(types.Integer, primary_key=True)
20+
first_name = Column(types.String, doc="The name of the user.")
21+
last_name = Column(types.String(255), doc="The surname of the user.")
22+
dob = Column(types.Date, nullable=False, doc="The date of birth.")
23+
24+
25+
class TestUserMultilineDocstringD213(Base):
26+
"""A ``user``.
27+
28+
The user has a multi-line docstring::
29+
30+
This is an indented code block
31+
32+
This is the last line of the docstring.
33+
"""
34+
35+
__tablename__ = "dbusers_d213"
36+
__table_args__ = (UniqueConstraint("first_name", "last_name"),)
37+
pk = Column(types.Integer, primary_key=True)
38+
first_name = Column(types.String, doc="The name of the user.")
39+
last_name = Column(types.String(255), doc="The surname of the user.")
40+
dob = Column(types.Date, nullable=False, doc="The date of birth.")

‎tests/test_docstrings.py

+33
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
"""Basic tests"""
2+
import os.path
3+
import sys
4+
5+
from sphinx_pytest.plugin import CreateDoctree
6+
7+
8+
def test_multiline_docstring_d212(sphinx_doctree_no_tr: CreateDoctree, snapshot):
9+
"""Basic test for models with multiline docstring with D212 format
10+
11+
see: https://docs.astral.sh/ruff/rules/multi-line-summary-first-line
12+
"""
13+
sys.path.insert(0, os.path.join(os.path.dirname(__file__), "modules"))
14+
sphinx_doctree_no_tr.set_conf({"extensions": ["sphinx_sqlalchemy"]})
15+
result = sphinx_doctree_no_tr(
16+
".. sqla-model:: module2.TestUserMultilineDocstringD212"
17+
)
18+
assert not result.warnings
19+
assert "\n".join([li.rstrip() for li in result.pformat().splitlines()]) == snapshot
20+
21+
22+
def test_multiline_docstring_d213(sphinx_doctree_no_tr: CreateDoctree, snapshot):
23+
"""Basic test for models with multiline docstring with D213 format
24+
25+
see: https://docs.astral.sh/ruff/rules/multi-line-summary-second-line
26+
"""
27+
sys.path.insert(0, os.path.join(os.path.dirname(__file__), "modules"))
28+
sphinx_doctree_no_tr.set_conf({"extensions": ["sphinx_sqlalchemy"]})
29+
result = sphinx_doctree_no_tr(
30+
".. sqla-model:: module2.TestUserMultilineDocstringD213"
31+
)
32+
assert not result.warnings
33+
assert "\n".join([li.rstrip() for li in result.pformat().splitlines()]) == snapshot

0 commit comments

Comments
 (0)