Skip to content

Commit 16cbdba

Browse files
authored
DOP-5477 Follow up - strict order on composable options, dedupe selections (#654)
* allow mixing order of composables. dedupe selections when repeated * add a try/catch for noindex error * change error type to invalidchildcount for verbosity
1 parent 357bae0 commit 16cbdba

File tree

2 files changed

+112
-28
lines changed

2 files changed

+112
-28
lines changed

snooty/parser.py

Lines changed: 26 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -893,6 +893,8 @@ def handle_composable(self, node: n.ComposableDirective) -> None:
893893
used_ids: Set[str] = set()
894894
composable_options = []
895895
default_ids_dict: Dict[str, str] = {}
896+
ordered_spec_composables: List[Composable] = []
897+
896898
for index in range(len(option_ids)):
897899
option_id = option_ids[index]
898900
try:
@@ -916,6 +918,7 @@ def handle_composable(self, node: n.ComposableDirective) -> None:
916918
)
917919
)
918920
continue
921+
ordered_spec_composables.append(composable_from_spec)
919922
specified_default_id = default_ids[index]
920923
allowed_values_dict = {
921924
option.id: option for option in composable_from_spec.options
@@ -953,7 +956,7 @@ def handle_composable(self, node: n.ComposableDirective) -> None:
953956
try:
954957
self.check_valid_child(node, child, {"selected-content"})
955958
assert isinstance(child, n.ComposableContent)
956-
self.handle_composable_content(child, spec_composables)
959+
self.handle_composable_content(child, ordered_spec_composables)
957960
valid_children.append(child)
958961

959962
# populate parent composable-tutorial with selections used by children
@@ -1002,16 +1005,18 @@ def handle_composable(self, node: n.ComposableDirective) -> None:
10021005
composable_option["selections"] = (
10031006
composable_option["selections"] or []
10041007
)
1005-
if isinstance(composable_option["selections"], list):
1006-
composable_option["selections"].append(
1007-
{
1008-
"value": option_from_spec.id,
1009-
"text": option_from_spec.title,
1010-
}
1011-
)
1008+
selection = {
1009+
"value": option_from_spec.id,
1010+
"text": option_from_spec.title,
1011+
}
1012+
if (
1013+
isinstance(composable_option["selections"], list)
1014+
and selection not in composable_option["selections"]
1015+
):
1016+
composable_option["selections"].append(selection)
10121017

10131018
default_values_found = default_values_found or all(
1014-
child.selections[composable_id] == option_id
1019+
child.selections.get(composable_id, "") == option_id
10151020
for composable_id, option_id in (default_ids_dict.items())
10161021
)
10171022

@@ -1039,7 +1044,18 @@ def handle_composable_content(
10391044
# validate all selection ids
10401045
for idx in range(len(selection_ids)):
10411046
selection_id = selection_ids[idx]
1042-
spec_composable = spec_composables[idx]
1047+
try:
1048+
spec_composable = spec_composables[idx]
1049+
except IndexError:
1050+
self.diagnostics.append(
1051+
InvalidChildCount(
1052+
"selected-content",
1053+
"selections",
1054+
str(len(spec_composables)),
1055+
node.start[0],
1056+
)
1057+
)
1058+
break
10431059
allowed_selection_ids = list(map(lambda x: x.id, spec_composable.options))
10441060
# check if dependencies are met - then None is not allowed
10451061
met_dependencies: bool = all(

snooty/test_parser.py

Lines changed: 86 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
IncorrectLinkSyntax,
1616
IncorrectMonospaceSyntax,
1717
InvalidChild,
18+
InvalidChildCount,
1819
InvalidDirectiveStructure,
1920
InvalidField,
2021
InvalidLiteralInclude,
@@ -4603,50 +4604,117 @@ def test_valid_composable_tutorial() -> None:
46034604
path,
46044605
"""
46054606
.. composable-tutorial::
4606-
:options: interface, language, cluster-topology, cloud-provider
4607-
:defaults: driver, nodejs, repl, gcp
4607+
:options: interface, language, deployment-type, cloud-provider
4608+
:defaults: driver, nodejs, atlas, gcp
46084609
46094610
.. selected-content::
4610-
:selections: driver, nodejs, repl, gcp
4611+
:selections: driver, nodejs, atlas, gcp
46114612
46124613
This content will only be shown when the selections are as follows:
46134614
Interface - Drivers
4614-
Language - Node
4615-
Deployment Type - Replication
4615+
Language - NodeJS
4616+
Deployment Type - Atlas
46164617
Cloud Provider - GCP
46174618
46184619
.. selected-content::
4619-
:selections: atlas-ui, None, repl, aws
4620+
:selections: driver, c, atlas, gcp
4621+
4622+
This content will only be shown when the selections are as follows:
4623+
Interface - Drivers
4624+
Language - C
4625+
Deployment Type - atlas
4626+
Cloud Provider - GCP
4627+
4628+
.. selected-content::
4629+
:selections: driver, cpp, atlas, aws
4630+
4631+
This content will only be shown when the selections are as follows:
4632+
Interface - Drivers
4633+
Language - CPP
4634+
Deployment Type - atlas
4635+
Cloud Provider - AWS
4636+
4637+
4638+
.. selected-content::
4639+
:selections: atlas-admin-api, None, atlas, gcp
46204640
46214641
This content will only be shown when the selections are as follows:
4622-
Interface - Atlas UI
4623-
Deployment Type - Replication
4642+
Interface - Atlas Admin API
4643+
Deployment Type - atlas
46244644
Cloud Provider - GCP
4645+
4646+
4647+
.. selected-content::
4648+
:selections: atlas-admin-api, None, atlas, aws
4649+
4650+
This content will only be shown when the selections are as follows:
4651+
Interface - Atlas Admin API
4652+
Deployment Type - Atlas
4653+
Cloud Provider - AWS
4654+
4655+
4656+
4657+
.. selected-content::
4658+
:selections: atlas-admin-api, None, self, aws
4659+
4660+
This content will only be shown when the selections are as follows:
4661+
Interface - Atlas Admin API
4662+
Deployment Type - self
4663+
Cloud Provider - AWS
46254664
""",
46264665
)
4627-
46284666
assert not diagnostics
46294667
check_ast_testing_string(
46304668
page.ast,
46314669
"""
46324670
<root fileid="test.rst">
46334671
<directive domain="mongodb" name="composable-tutorial"
4634-
composable_options="[{'value': 'interface', 'text': 'Interface', 'default': 'driver', 'dependencies': [], 'selections': [{'value': 'driver', 'text': 'Driver'}, {'value': 'atlas-ui', 'text': 'Atlas UI'}]}, {'value': 'language', 'text': 'Language', 'default': 'nodejs', 'dependencies': [{'interface': 'driver'}], 'selections': [{'value': 'nodejs', 'text': 'Node.js'}]}, {'value': 'cluster-topology', 'text': 'Cluster Topology', 'default': 'repl', 'dependencies': [], 'selections': [{'value': 'repl', 'text': 'Replica Set'}, {'value': 'repl', 'text': 'Replica Set'}]}, {'value': 'cloud-provider', 'text': 'Cloud Provider', 'default': 'gcp', 'dependencies': [], 'selections': [{'value': 'gcp', 'text': 'GCP'}, {'value': 'aws', 'text': 'AWS'}]}]">
4672+
composable_options="[{'value': 'interface', 'text': 'Interface', 'default': 'driver', 'dependencies': [], 'selections': [{'value': 'driver', 'text': 'Driver'}, {'value': 'atlas-admin-api', 'text': 'Atlas Admin API'}]}, {'value': 'language', 'text': 'Language', 'default': 'nodejs', 'dependencies': [{'interface': 'driver'}], 'selections': [{'value': 'nodejs', 'text': 'Node.js'}, {'value': 'c', 'text': 'C'}, {'value': 'cpp', 'text': 'C++'}]}, {'value': 'deployment-type', 'text': 'Deployment Type', 'default': 'atlas', 'dependencies': [], 'selections': [{'value': 'atlas', 'text': 'Atlas (Cloud)'}, {'value': 'self', 'text': 'Self-Managed (On-premises)'}]}, {'value': 'cloud-provider', 'text': 'Cloud Provider', 'default': 'gcp', 'dependencies': [], 'selections': [{'value': 'gcp', 'text': 'GCP'}, {'value': 'aws', 'text': 'AWS'}]}]">
46354673
<directive domain="mongodb" name="selected-content"
4636-
selections="{'interface': 'driver', 'language': 'nodejs', 'cluster-topology': 'repl', 'cloud-provider': 'gcp'}">
4674+
selections="{'interface': 'driver', 'language': 'nodejs', 'deployment-type': 'atlas', 'cloud-provider': 'gcp'}">
46374675
<paragraph><text>This content will only be shown when the selections are as follows:
46384676
Interface - Drivers
4639-
Language - Node
4640-
Deployment Type - Replication
4677+
Language - NodeJS
4678+
Deployment Type - Atlas
46414679
Cloud Provider - GCP</text></paragraph>
46424680
</directive>
46434681
<directive domain="mongodb" name="selected-content"
4644-
selections="{'interface': 'atlas-ui', 'language': 'None', 'cluster-topology': 'repl', 'cloud-provider': 'aws'}">
4682+
selections="{'interface': 'driver', 'language': 'c', 'deployment-type': 'atlas', 'cloud-provider': 'gcp'}">
46454683
<paragraph><text>This content will only be shown when the selections are as follows:
4646-
Interface - Atlas UI
4647-
Deployment Type - Replication
4684+
Interface - Drivers
4685+
Language - C
4686+
Deployment Type - atlas
46484687
Cloud Provider - GCP</text></paragraph>
46494688
</directive>
4689+
<directive domain="mongodb" name="selected-content"
4690+
selections="{'interface': 'driver', 'language': 'cpp', 'deployment-type': 'atlas', 'cloud-provider': 'aws'}">
4691+
<paragraph><text>This content will only be shown when the selections are as follows:
4692+
Interface - Drivers
4693+
Language - CPP
4694+
Deployment Type - atlas
4695+
Cloud Provider - AWS</text></paragraph>
4696+
</directive>
4697+
<directive domain="mongodb" name="selected-content"
4698+
selections="{'interface': 'atlas-admin-api', 'language': 'None', 'deployment-type': 'atlas', 'cloud-provider': 'gcp'}">
4699+
<paragraph><text>This content will only be shown when the selections are as follows:
4700+
Interface - Atlas Admin API
4701+
Deployment Type - atlas
4702+
Cloud Provider - GCP</text></paragraph>
4703+
</directive>
4704+
<directive domain="mongodb" name="selected-content"
4705+
selections="{'interface': 'atlas-admin-api', 'language': 'None', 'deployment-type': 'atlas', 'cloud-provider': 'aws'}">
4706+
<paragraph><text>This content will only be shown when the selections are as follows:
4707+
Interface - Atlas Admin API
4708+
Deployment Type - Atlas
4709+
Cloud Provider - AWS</text></paragraph>
4710+
</directive>
4711+
<directive domain="mongodb" name="selected-content"
4712+
selections="{'interface': 'atlas-admin-api', 'language': 'None', 'deployment-type': 'self', 'cloud-provider': 'aws'}">
4713+
<paragraph><text>This content will only be shown when the selections are as follows:
4714+
Interface - Atlas Admin API
4715+
Deployment Type - self
4716+
Cloud Provider - AWS</text></paragraph>
4717+
</directive>
46504718
</directive>
46514719
</root>
46524720
""",
@@ -4675,8 +4743,8 @@ def test_composable_tutorial_errors() -> None:
46754743
UnknownOptionId,
46764744
# invalid composable tutorial option cloud-providerr
46774745
UnknownOptionId,
4678-
# invalid selection gcpp
4679-
UnknownOptionId,
4746+
# invalid child count gcppgcpppppp
4747+
InvalidChildCount,
46804748
]
46814749

46824750
_page, diagnostics = parse_rst(

0 commit comments

Comments
 (0)