Skip to content

Commit 7ba80e0

Browse files
committed
Fix Sphinx build warnings (#10)
There were a few obscure warnings about backticks and pipes, as well as some indendation issues. Those are all fixed now.
1 parent 6ae5001 commit 7ba80e0

2 files changed

Lines changed: 57 additions & 11 deletions

File tree

generator/generate.py

Lines changed: 47 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
import operator
88
import os
99
from pathlib import Path
10+
import re
1011
from textwrap import dedent, indent as tw_indent
1112
import typing
1213

@@ -48,11 +49,39 @@ def indent(s: str, n: int):
4849
return tw_indent(s, n * ' ')
4950

5051

52+
BACKTICK_RE = re.compile(r'`([^`]+)`(\w+)?')
53+
54+
55+
def escape_backticks(docstr: str) -> str:
56+
'''
57+
Escape backticks in a docstring by doubling them up.
58+
59+
This is a little tricky because RST requires a non-letter character after
60+
the closing backticks, but some CDPs docs have things like "`AxNodeId`s".
61+
If we double the backticks in that string, then it won't be valid RST. The
62+
fix is to insert an apostrophe if an "s" trails the backticks.
63+
'''
64+
def replace_one(match):
65+
if match.group(2) == 's':
66+
return f"``{match.group(1)}``'s"
67+
elif match.group(2):
68+
# This case (some trailer other than "s") doesn't currently exist
69+
# in the CDP definitions, but it's here just to be safe.
70+
return f'``{match.group(1)}`` {match.group(2)}'
71+
else:
72+
return f'``{match.group(1)}``'
73+
74+
# Sometimes pipes are used where backticks should have been used.
75+
docstr = docstr.replace('|', '`')
76+
return BACKTICK_RE.sub(replace_one, docstr)
77+
78+
5179
def inline_doc(description) -> str:
5280
''' Generate an inline doc, e.g. ``#: This type is a ...`` '''
5381
if not description:
5482
return ''
5583

84+
description = escape_backticks(description)
5685
lines = ['#: {}'.format(l) for l in description.split('\n')]
5786
return '\n'.join(lines)
5887

@@ -62,6 +91,7 @@ def docstring(description: typing.Optional[str]) -> str:
6291
if not description:
6392
return ''
6493

94+
description = escape_backticks(description)
6595
return dedent("'''\n{}\n'''").format(description)
6696

6797

@@ -501,7 +531,7 @@ def py_annotation(self):
501531
def generate_doc(self):
502532
''' Generate the docstring for this return. '''
503533
if self.description:
504-
doc = self.description.replace('`', '``')
534+
doc = self.description.replace('`', '``').replace('\n', ' ')
505535
if self.optional:
506536
doc = f'*(Optional)* {doc}'
507537
else:
@@ -575,14 +605,13 @@ def generate_code(self) -> str:
575605
code += ret
576606

577607
# Generate the docstring
608+
doc = ''
609+
if self.description:
610+
doc = self.description
578611
if self.deprecated:
579-
doc = f'.. deprecated:: {current_version}'
580-
else:
581-
doc = ''
612+
doc += f'\n\n.. deprecated:: {current_version}'
582613
if self.experimental:
583-
doc += f'**EXPERIMENTAL**\n\n'
584-
if self.description:
585-
doc += self.description
614+
doc += f'\n\n**EXPERIMENTAL**'
586615
if self.parameters and doc:
587616
doc += '\n\n'
588617
elif not self.parameters and self.returns:
@@ -875,6 +904,7 @@ def generate_docs(docs_path, domains):
875904
with doc.open('w') as f:
876905
f.write(domain.generate_sphinx())
877906

907+
878908
def main():
879909
''' Main entry point. '''
880910
here = Path(__file__).parent.resolve()
@@ -897,15 +927,21 @@ def main():
897927
domains.extend(parse(json_path, output_path))
898928
domains.sort(key=operator.attrgetter('domain'))
899929

900-
# The DOM domain includes an erroneous $ref that refers to itself. It's
901-
# easier to patch that here than it is to modify the generator code.
930+
# Patch up CDP errors. It's easier to patch that here than it is to modify
931+
# the generator code.
932+
# 1. DOM includes an erroneous $ref that refers to itself.
933+
# 2. Page includes an event with an extraneous backtick in the description.
902934
for domain in domains:
903935
if domain.domain == 'DOM':
904936
for cmd in domain.commands:
905937
if cmd.name == 'resolveNode':
938+
# Patch 1
906939
cmd.parameters[1].ref = 'BackendNodeId'
907-
break
908-
break
940+
elif domain.domain == 'Page':
941+
for event in domain.events:
942+
if event.name == 'screencastVisibilityChanged':
943+
# Patch 2
944+
event.description = event.description.replace('`', '')
909945

910946
for domain in domains:
911947
logger.info('Generating module: %s → %s.py', domain.domain,

generator/test_generate.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,16 @@ def test_docstring():
3737
assert expected == actual
3838

3939

40+
def test_escape_docstring():
41+
description = 'Escape a `Backtick` and some `Backtick`s.'
42+
expected = dedent("""\
43+
'''
44+
Escape a ``Backtick`` and some ``Backtick``'s.
45+
'''""")
46+
actual = docstring(description)
47+
assert expected == actual
48+
49+
4050
def test_cdp_primitive_type():
4151
json_type = {
4252
"id": "AXNodeId",

0 commit comments

Comments
 (0)