Skip to content

Commit ff45dea

Browse files
authored
DOP-1129: Handle additional ordered list types (#174)
* Handle ordered list types * Use enumtype * Combine ordered property with enumtype * Address @i80and feedback
1 parent a874c25 commit ff45dea

File tree

5 files changed

+108
-55
lines changed

5 files changed

+108
-55
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1010
### Added
1111

1212
- fail_on_diagnostics toml flag (DOP-1132)
13+
- Support additional ordered list labels (DOP-1129)
1314

1415
## [v0.4.11] - 2020-06-22
1516

snooty/n.py

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import dataclasses
2+
from enum import Enum
23
from typing import (
34
Any,
45
ClassVar,
@@ -37,6 +38,10 @@
3738

3839
SerializableType = Union[None, bool, str, int, float, Dict[str, Any], List[Any]]
3940
SerializedNode = Dict[str, SerializableType]
41+
ListEnumType = Enum(
42+
"ListEnumType",
43+
("unordered", "arabic", "loweralpha", "upperalpha", "lowerroman", "upperroman"),
44+
)
4045
_T = TypeVar("_T")
4146

4247

@@ -65,6 +70,8 @@ def serialize(self) -> SerializedNode:
6570
# We exclude empty dicts, since they're mainly used for directive options and other such things.
6671
if value:
6772
result[field.name] = value
73+
elif isinstance(value, Enum):
74+
result[field.name] = value.name
6875
elif isinstance(value, (list, tuple)):
6976
# This is a bit unsafe, but it's the most expedient option right now. If the child
7077
# has a serialize() method, call that; otherwise, include it as-is.
@@ -226,9 +233,9 @@ class ListNodeItem(Parent[Node]):
226233

227234
@dataclass
228235
class ListNode(Parent[ListNodeItem]):
229-
__slots__ = ("ordered",)
236+
__slots__ = "enumtype"
230237
type = "list"
231-
ordered: bool
238+
enumtype: ListEnumType
232239

233240

234241
@dataclass

snooty/parser.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -234,9 +234,9 @@ def dispatch_visit(self, node: docutils.nodes.Node) -> None:
234234
elif isinstance(node, docutils.nodes.definition_list_item):
235235
self.state.append(n.DefinitionListItem((line,), [], []))
236236
elif isinstance(node, docutils.nodes.bullet_list):
237-
self.state.append(n.ListNode((line,), [], False))
237+
self.state.append(n.ListNode((line,), [], n.ListEnumType.unordered))
238238
elif isinstance(node, docutils.nodes.enumerated_list):
239-
self.state.append(n.ListNode((line,), [], True))
239+
self.state.append(n.ListNode((line,), [], n.ListEnumType[node["enumtype"]]))
240240
elif isinstance(node, docutils.nodes.list_item):
241241
self.state.append(n.ListNodeItem((line,), []))
242242
elif isinstance(node, docutils.nodes.title):

snooty/test_legacy_guides.py

Lines changed: 42 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -17,53 +17,48 @@ def test_legacy_guides() -> None:
1717
legacy_page.finish(legacy_diagnostics)
1818
new_page.finish(new_diagnostics)
1919

20-
correct = "".join(
21-
(
22-
'<root guide="">',
23-
'<section><heading id="sample-app"><text>Sample App</text></heading>',
24-
'<directive name="author"><text>MongoDB</text></directive>',
25-
'<directive name="category"><text>Getting Started</text></directive>',
26-
'<directive name="languages"><list>',
27-
"<listItem><paragraph><text>shell</text></paragraph></listItem>",
28-
"<listItem><paragraph><text>java-sync</text></paragraph></listItem>",
29-
"</list></directive>",
30-
'<directive name="level"><text>beginner</text></directive>',
31-
'<directive name="product_version"><text>4.0</text></directive>',
32-
'<directive name="result_description"><paragraph><text>In this guide...</text>',
33-
"</paragraph></directive>",
34-
'<directive name="time"><text>15</text></directive>',
35-
'<directive name="prerequisites">',
36-
"<paragraph><text>Before you start this Guide...</text></paragraph>",
37-
"<paragraph><text>The ",
38-
'</text><reference refuri="https://docs.mongodb.com/stitch/authentication/google/">',
39-
"<text>Google Authentication Page</text></reference><text>.</text></paragraph></directive>",
40-
'<directive name="check_your_environment"><paragraph><text>stuff</text></paragraph>',
41-
'</directive><directive name="procedure"><paragraph><text>stuff</text></paragraph>',
42-
'</directive><directive name="summary"><paragraph><text>stuff</text></paragraph>',
43-
'</directive><directive name="whats_next"><paragraph><text>stuff</text></paragraph>',
44-
"</directive>",
45-
'<directive name="guide-index">',
46-
'<directive name="card"><text>server/introduction</text></directive>',
47-
'<directive name="card"><text>server/auth</text></directive>',
48-
'<directive name="multi-card"><text>MongoDB in the Cloud</text>',
49-
"<list><listItem><paragraph><text>cloud/atlas</text></paragraph></listItem>",
50-
"<listItem><paragraph><text>cloud/connectionstring</text></paragraph></listItem></list>",
51-
"</directive>",
52-
'<directive name="multi-card"><text>Migrate to MongoDB Atlas</text>',
53-
"<list><listItem><paragraph><text>cloud/migrate-from-aws-to-atlas</text></paragraph>",
54-
"</listItem></list></directive>",
55-
'<directive name="card"><text>server/import</text></directive>',
56-
'<directive name="card"><text>server/drivers</text></directive>',
57-
'<directive name="multi-card">',
58-
"<text>CRUD Guides: Create, Read, Update, and Delete Data</text><list>",
59-
"<listItem><paragraph><text>server/insert</text></paragraph></listItem>",
60-
"<listItem><paragraph><text>server/read</text></paragraph></listItem>",
61-
"</list></directive>",
62-
'<directive name="card"><text>stitch/react_googleauth</text></directive></directive>',
63-
"</section>",
64-
"</root>",
65-
)
66-
)
20+
correct = """<root guide="">
21+
<section><heading id="sample-app"><text>Sample App</text></heading>
22+
<directive name="author"><text>MongoDB</text></directive>
23+
<directive name="category"><text>Getting Started</text></directive>
24+
<directive name="languages"><list enumtype="unordered">
25+
<listItem><paragraph><text>shell</text></paragraph></listItem>
26+
<listItem><paragraph><text>java-sync</text></paragraph></listItem>
27+
</list></directive>
28+
<directive name="level"><text>beginner</text></directive>
29+
<directive name="product_version"><text>4.0</text></directive>
30+
<directive name="result_description"><paragraph><text>In this guide...</text>
31+
</paragraph></directive>
32+
<directive name="time"><text>15</text></directive>
33+
<directive name="prerequisites">
34+
<paragraph><text>Before you start this Guide...</text></paragraph>
35+
<paragraph><text>The </text><reference refuri="https://docs.mongodb.com/stitch/authentication/google/">
36+
<text>Google Authentication Page</text></reference><text>.</text></paragraph></directive>
37+
<directive name="check_your_environment"><paragraph><text>stuff</text></paragraph>
38+
</directive><directive name="procedure"><paragraph><text>stuff</text></paragraph>
39+
</directive><directive name="summary"><paragraph><text>stuff</text></paragraph>
40+
</directive><directive name="whats_next"><paragraph><text>stuff</text></paragraph>
41+
</directive>
42+
<directive name="guide-index">
43+
<directive name="card"><text>server/introduction</text></directive>
44+
<directive name="card"><text>server/auth</text></directive>
45+
<directive name="multi-card"><text>MongoDB in the Cloud</text>
46+
<list enumtype="unordered"><listItem><paragraph><text>cloud/atlas</text></paragraph></listItem>
47+
<listItem><paragraph><text>cloud/connectionstring</text></paragraph></listItem></list>
48+
</directive>
49+
<directive name="multi-card"><text>Migrate to MongoDB Atlas</text>
50+
<list enumtype="unordered"><listItem><paragraph><text>cloud/migrate-from-aws-to-atlas</text></paragraph>
51+
</listItem></list></directive>
52+
<directive name="card"><text>server/import</text></directive>
53+
<directive name="card"><text>server/drivers</text></directive>
54+
<directive name="multi-card">
55+
<text>CRUD Guides: Create, Read, Update, and Delete Data</text><list enumtype="unordered">
56+
<listItem><paragraph><text>server/insert</text></paragraph></listItem>
57+
<listItem><paragraph><text>server/read</text></paragraph></listItem>
58+
</list></directive>
59+
<directive name="card"><text>stitch/react_googleauth</text></directive></directive>
60+
</section>
61+
</root>"""
6762

6863
# Ensure that legacy syntax and new syntax create the same output
6964
check_ast_testing_string(legacy_page.ast, correct)

snooty/test_parser.py

Lines changed: 54 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -444,7 +444,7 @@ def test_admonition() -> None:
444444
page.ast,
445445
"""<root>
446446
<directive name="note">
447-
<list><listItem><paragraph><text>foo</text></paragraph></listItem>
447+
<list enumtype="unordered"><listItem><paragraph><text>foo</text></paragraph></listItem>
448448
<listItem><paragraph><text>bar</text></paragraph></listItem></list>
449449
</directive>
450450
</root>""",
@@ -552,7 +552,7 @@ def test_roles() -> None:
552552
<directive_argument><literal><text>mongod</text></literal></directive_argument>
553553
<target_identifier ids="['bin.mongod']"><text>mongod</text></target_identifier>
554554
</target>
555-
<list>
555+
<list enumtype="unordered">
556556
<listItem>
557557
<paragraph>
558558
<reference refuri="https://docs.mongodb.com/manual/introduction/">
@@ -642,7 +642,7 @@ def test_doc_role() -> None:
642642
page.ast,
643643
"""
644644
<root>
645-
<list>
645+
<list enumtype="unordered">
646646
<listItem>
647647
<paragraph>
648648
<ref_role domain="std" name="doc" fileid="/index">
@@ -1039,6 +1039,56 @@ def test_version() -> None:
10391039
)
10401040

10411041

1042+
def test_list() -> None:
1043+
path = ROOT_PATH.joinpath(Path("test.rst"))
1044+
project_config = ProjectConfig(ROOT_PATH, "", source="./")
1045+
parser = rstparser.Parser(project_config, JSONVisitor)
1046+
1047+
page, diagnostics = parse_rst(
1048+
parser,
1049+
path,
1050+
"""
1051+
- First bulleted item
1052+
- Second
1053+
- Third
1054+
""",
1055+
)
1056+
page.finish(diagnostics)
1057+
assert len(diagnostics) == 0
1058+
check_ast_testing_string(
1059+
page.ast,
1060+
"""<root>
1061+
<list enumtype="unordered">
1062+
<listItem><paragraph><text>First bulleted item</text></paragraph></listItem>
1063+
<listItem><paragraph><text>Second</text></paragraph></listItem>
1064+
<listItem><paragraph><text>Third</text></paragraph></listItem>
1065+
</list>
1066+
</root>""",
1067+
)
1068+
1069+
page, diagnostics = parse_rst(
1070+
parser,
1071+
path,
1072+
"""
1073+
a. First list item
1074+
#. Second
1075+
#. Third
1076+
""",
1077+
)
1078+
page.finish(diagnostics)
1079+
assert len(diagnostics) == 0
1080+
check_ast_testing_string(
1081+
page.ast,
1082+
"""<root>
1083+
<list enumtype="loweralpha">
1084+
<listItem><paragraph><text>First list item</text></paragraph></listItem>
1085+
<listItem><paragraph><text>Second</text></paragraph></listItem>
1086+
<listItem><paragraph><text>Third</text></paragraph></listItem>
1087+
</list>
1088+
</root>""",
1089+
)
1090+
1091+
10421092
def test_list_table() -> None:
10431093
path = ROOT_PATH.joinpath(Path("test.rst"))
10441094
project_config = ProjectConfig(ROOT_PATH, "", source="./")
@@ -1389,7 +1439,7 @@ def test_callable_target() -> None:
13891439
<text>Creates an index on the specified field if the index does not already exist.</text>
13901440
</paragraph>
13911441
</target>
1392-
<list>
1442+
<list enumtype="unordered">
13931443
<listItem><paragraph>
13941444
<ref_role domain="mongodb" name="method" target="db.collection.ensureIndex"><literal /></ref_role>
13951445
</paragraph></listItem>

0 commit comments

Comments
 (0)