|
7 | 7 | import subprocess
|
8 | 8 |
|
9 | 9 | if len(sys.argv) < 2:
|
10 |
| - print('Must provide a path to an RST file') |
| 10 | + print("Must provide a path to an RST file") |
11 | 11 | sys.exit(1)
|
12 | 12 |
|
13 | 13 | path = Path(sys.argv[1])
|
14 | 14 |
|
15 | 15 | # Ensure git history for the md file.
|
16 |
| -md_file = str(path).replace('.rst', '.md') |
17 |
| -subprocess.check_call(['git', 'mv', path, md_file]) |
18 |
| -subprocess.check_call(['git', 'add', md_file]) |
19 |
| -subprocess.check_call(['git', 'commit', '--no-verify', '-m', f'Rename {path} to {md_file}']) |
20 |
| -subprocess.check_call(['git', 'checkout', 'HEAD~1', path]) |
21 |
| -subprocess.check_call(['git', 'add', path]) |
| 16 | +md_file = str(path).replace(".rst", ".md") |
| 17 | +subprocess.check_call(["git", "mv", path, md_file]) |
| 18 | +subprocess.check_call(["git", "add", md_file]) |
| 19 | +subprocess.check_call( |
| 20 | + ["git", "commit", "--no-verify", "-m", f"Rename {path} to {md_file}"] |
| 21 | +) |
| 22 | +subprocess.check_call(["git", "checkout", "HEAD~1", path]) |
| 23 | +subprocess.check_call(["git", "add", path]) |
22 | 24 |
|
23 | 25 | # Get the contents of the file.
|
24 | 26 | with path.open() as fid:
|
|
31 | 33 | """
|
32 | 34 |
|
33 | 35 | # Update the RST file with a stub pointer to the MD file.
|
34 |
| -if not path.name == 'README.rst': |
| 36 | +if not path.name == "README.rst": |
35 | 37 | new_body = TEMPLATE.format(os.path.basename(md_file))
|
36 |
| - with path.open('w') as fid: |
37 |
| - fid.write(''.join(new_body)) |
| 38 | + with path.open("w") as fid: |
| 39 | + fid.write("".join(new_body)) |
38 | 40 |
|
39 | 41 | # Pre-process the file.
|
40 |
| -for (i, line) in enumerate(lines): |
| 42 | +for i, line in enumerate(lines): |
41 | 43 | # Replace curly quotes with regular quotes.
|
42 |
| - line = line.replace('”', '"') |
43 |
| - line = line.replace('“', '"') |
44 |
| - line = line.replace('’', "'") |
45 |
| - line = line.replace('‘', "'") |
| 44 | + line = line.replace("”", '"') |
| 45 | + line = line.replace("“", '"') |
| 46 | + line = line.replace("’", "'") |
| 47 | + line = line.replace("‘", "'") |
46 | 48 | lines[i] = line
|
47 | 49 |
|
48 | 50 | # Replace the colon fence blocks with bullets,
|
49 | 51 | # e.g. :Status:, :deprecated:, :changed:.
|
50 | 52 | # This also includes the changelog entries.
|
51 |
| - match = re.match(r':(\S+):(.*)', line) |
| 53 | + match = re.match(r":(\S+):(.*)", line) |
52 | 54 | if match:
|
53 | 55 | name, value = match.groups()
|
54 |
| - lines[i] = f'- {name.capitalize()}:{value}\n' |
| 56 | + lines[i] = f"- {name.capitalize()}:{value}\n" |
55 | 57 |
|
56 | 58 | # Handle "":Minimum Server Version:"" as a block quote.
|
57 |
| - if line.strip().startswith(':Minimum Server Version:'): |
58 |
| - lines[i] = '- ' + line.strip()[1:] + '' |
| 59 | + if line.strip().startswith(":Minimum Server Version:"): |
| 60 | + lines[i] = "- " + line.strip()[1:] + "" |
59 | 61 |
|
60 | 62 | # Remove the "".. contents::" block - handled by GitHub UI.
|
61 |
| - if line.strip() == '.. contents::': |
62 |
| - lines[i] = '' |
| 63 | + if line.strip() == ".. contents::": |
| 64 | + lines[i] = "" |
63 | 65 |
|
64 | 66 | # Run pandoc and capture output.
|
65 |
| -proc = subprocess.Popen(['pandoc', '-f', 'rst', '-t', 'gfm'], stdin=subprocess.PIPE, stdout=subprocess.PIPE) |
66 |
| -data = ''.join(lines).encode('utf8') |
| 67 | +proc = subprocess.Popen( |
| 68 | + ["pandoc", "-f", "rst", "-t", "gfm"], stdin=subprocess.PIPE, stdout=subprocess.PIPE |
| 69 | +) |
| 70 | +data = "".join(lines).encode("utf8") |
67 | 71 | outs, _ = proc.communicate(data)
|
68 |
| -data = outs.decode('utf8') |
| 72 | +data = outs.decode("utf8") |
69 | 73 |
|
70 | 74 | # Fix the strings that were missing backticks.
|
71 |
| -data = re.sub(r'<span\W+class="title-ref">', '`', data, flags=re.MULTILINE) |
72 |
| -data = data.replace('</span>', '`') |
| 75 | +data = re.sub(r'<span\W+class="title-ref">', "`", data, flags=re.MULTILINE) |
| 76 | +data = data.replace("</span>", "`") |
73 | 77 |
|
74 | 78 | # Handle div blocks that were created.
|
75 | 79 | # These are admonition blocks, convert to new GFM format.
|
|
79 | 83 | in_changelog_first = False
|
80 | 84 | lines = data.splitlines()
|
81 | 85 | new_lines = []
|
82 |
| -for (i, line) in enumerate(lines): |
83 |
| - match = re.match(r'<div class="(\S+)">',line) |
| 86 | +for i, line in enumerate(lines): |
| 87 | + match = re.match(r'<div class="(\S+)">', line) |
84 | 88 | if not in_block_outer and match:
|
85 | 89 | in_block_outer = True
|
86 |
| - new_lines.append(f'> [!{match.groups()[0].upper()}]') |
| 90 | + new_lines.append(f"> [!{match.groups()[0].upper()}]") |
87 | 91 | continue
|
88 |
| - if line.strip() == '</div>': |
| 92 | + if line.strip() == "</div>": |
89 | 93 | if in_block_outer:
|
90 | 94 | in_block_outer = False
|
91 | 95 | in_block_inner = True
|
92 | 96 | elif in_block_inner:
|
93 | 97 | in_block_inner = False
|
94 | 98 | continue
|
95 | 99 | if in_block_inner:
|
96 |
| - line = '> ' + line.strip() |
| 100 | + line = "> " + line.strip() |
97 | 101 |
|
98 | 102 | if in_changelog_first:
|
99 |
| - today = datetime.date.today().strftime('%Y-%m-%d') |
100 |
| - line = f'\n- {today}: Migrated from reStructuredText to Markdown.' |
| 103 | + today = datetime.date.today().strftime("%Y-%m-%d") |
| 104 | + line = f"\n- {today}: Migrated from reStructuredText to Markdown." |
101 | 105 | in_changelog_first = False
|
102 | 106 |
|
103 |
| - if line.strip() == '## Changelog': |
| 107 | + if line.strip() == "## Changelog": |
104 | 108 | in_changelog_first = True
|
105 | 109 |
|
106 | 110 | if not in_block_outer:
|
107 |
| - new_lines.append(line) |
| 111 | + new_lines.append(line) |
108 | 112 |
|
109 | 113 |
|
110 | 114 | # Write the new content to the markdown file.
|
111 |
| -with open(md_file, 'w') as fid: |
112 |
| - fid.write('\n'.join(new_lines)) |
| 115 | +with open(md_file, "w") as fid: |
| 116 | + fid.write("\n".join(new_lines)) |
113 | 117 |
|
114 | 118 | # Handle links in other files.
|
115 |
| -# We accept relative path links or links to master |
| 119 | +# We accept relative path links or links to master |
116 | 120 | # (https://github.com/mongodb/specifications/blob/master/source/...)
|
117 | 121 | # and rewrite them to use appropriate md links.
|
118 | 122 | # If the link is malformed we ignore and print an error.
|
119 | 123 | target = path.name
|
120 | 124 | curr = path
|
121 |
| -while curr.parent.name != 'source': |
122 |
| - target = f'{curr.parent.name}/{target}' |
| 125 | +while curr.parent.name != "source": |
| 126 | + target = f"{curr.parent.name}/{target}" |
123 | 127 | curr = curr.parent
|
124 |
| -suffix = fr'\S*/{target}' |
125 |
| -rel_pattern = re.compile(fr'(\.\.{suffix})') |
126 |
| -md_pattern = re.compile(fr'(\(http{suffix})') |
127 |
| -html_pattern = re.compile(f'(http{suffix})') |
128 |
| -abs_pattern = re.compile(f'(/source{suffix})') |
| 128 | +suffix = rf"\S*/{target}" |
| 129 | +rel_pattern = re.compile(rf"(\.\.{suffix})") |
| 130 | +md_pattern = re.compile(rf"(\(http{suffix})") |
| 131 | +html_pattern = re.compile(f"(http{suffix})") |
| 132 | +abs_pattern = re.compile(f"(/source{suffix})") |
129 | 133 | for p in Path("source").rglob("*"):
|
130 |
| - if p.suffix not in ['.rst', '.md']: |
| 134 | + if p.suffix not in [".rst", ".md"]: |
131 | 135 | continue
|
132 | 136 | with p.open() as fid:
|
133 | 137 | lines = fid.readlines()
|
|
141 | 145 | new_line = line.replace(matchstr, relpath)
|
142 | 146 | elif re.search(md_pattern, line):
|
143 | 147 | matchstr = re.search(md_pattern, line).groups()[0]
|
144 |
| - if not matchstr.startswith('(https://github.com/mongodb/specifications/blob/master/source'): |
145 |
| - print('*** Error in link: ', matchstr, p) |
| 148 | + if not matchstr.startswith( |
| 149 | + "(https://github.com/mongodb/specifications/blob/master/source" |
| 150 | + ): |
| 151 | + print("*** Error in link: ", matchstr, p) |
146 | 152 | else:
|
147 |
| - new_line = line.replace(matchstr, f'({relpath}') |
| 153 | + new_line = line.replace(matchstr, f"({relpath}") |
148 | 154 | elif re.search(html_pattern, line):
|
149 | 155 | matchstr = re.search(html_pattern, line).groups()[0]
|
150 |
| - if not matchstr.startswith('https://github.com/mongodb/specifications/blob/master/source'): |
151 |
| - print('*** Error in link: ', matchstr, p) |
| 156 | + if not matchstr.startswith( |
| 157 | + "https://github.com/mongodb/specifications/blob/master/source" |
| 158 | + ): |
| 159 | + print("*** Error in link: ", matchstr, p) |
152 | 160 | else:
|
153 |
| - new_line = line.replace(matchstr, f'{relpath}') |
| 161 | + new_line = line.replace(matchstr, f"{relpath}") |
154 | 162 | elif re.search(abs_pattern, line):
|
155 | 163 | matchstr = re.search(abs_pattern, line).groups()[0]
|
156 | 164 | new_line = line.replace(matchstr, relpath)
|
|
160 | 168 | new_lines.append(new_line)
|
161 | 169 |
|
162 | 170 | if changed_lines:
|
163 |
| - with p.open('w') as fid: |
| 171 | + with p.open("w") as fid: |
164 | 172 | fid.writelines(new_lines)
|
165 |
| - print('-' * 80) |
166 |
| - print(f'Updated link(s) in {p}...') |
167 |
| - print(' ' + '\n '.join(changed_lines)) |
| 173 | + print("-" * 80) |
| 174 | + print(f"Updated link(s) in {p}...") |
| 175 | + print(" " + "\n ".join(changed_lines)) |
168 | 176 |
|
169 |
| -print('Created markdown file:') |
| 177 | +print("Created markdown file:") |
170 | 178 | print(md_file)
|
0 commit comments