forked from godotengine/godot-docs
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add a tool to move rst files and images
The program moves a list of rst files along with their image dependencies to a target directory. It then outputs redirects in the format the ReadTheDocs backend expects.
- Loading branch information
1 parent
9a63228
commit 5e3a7c8
Showing
1 changed file
with
108 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,108 @@ | ||
import re | ||
from argparse import ArgumentParser | ||
from os.path import isfile, isdir, join, realpath, split, dirname, relpath | ||
import os | ||
import shutil | ||
|
||
|
||
def parse_and_get_arguments(): | ||
"""Creates and returns an object with parsed arguments, using argparse.""" | ||
parser: ArgumentParser = ArgumentParser( | ||
prog="move_rst_files", | ||
description="Moves reST documents and their dependencies from one folder to another. Outputs required redirections in the ReadTheDocs backend.", | ||
) | ||
parser.add_argument( | ||
"documents", nargs="+", help="Paths of documents to move.", | ||
) | ||
parser.add_argument( | ||
"output_path", help="Path to the target output directory.", | ||
) | ||
return parser.parse_args() | ||
|
||
|
||
def find_project_root_path(document_path): | ||
"""Returns the path to the repository's root directory by looking for the file conf.py, starting | ||
from the path of any file in the project.""" | ||
full_path = realpath(document_path) | ||
dirpath = split(full_path)[0] | ||
|
||
root_path = "" | ||
current = dirpath | ||
iterations = 0 | ||
while root_path == "": | ||
if isfile(join(current, "conf.py")): | ||
root_path = current | ||
else: | ||
current = split(current)[0] | ||
if current == "": | ||
break | ||
iterations += 1 | ||
if iterations > 20: | ||
break | ||
return root_path | ||
|
||
|
||
def find_images(document): | ||
"""Returns the list of image filepaths used by the `document`.""" | ||
images = [] | ||
for line in document: | ||
match = re.match(r"\.\. image::\s+(img\/.+)", line) | ||
if match: | ||
images.append(match[1]) | ||
return list(set(images)) | ||
|
||
|
||
def find_document_dependencies(documents): | ||
"""For each document path in `documents`, finds all pictures it depends on and returns a dict with the form { document: [images] }.""" | ||
data = {} | ||
for path in documents: | ||
with open(path, "r") as rst_file: | ||
images = find_images(rst_file) | ||
data[path] = images | ||
return data | ||
|
||
|
||
def move_documents(paths, output_path): | ||
"""Moves .rst files and all their image dependencies to `output_path`""" | ||
data = find_document_dependencies(paths) | ||
for path in data: | ||
directory = dirname(path) | ||
shutil.move(path, output_path) | ||
for image in data[path]: | ||
image_in_path = join(directory, image) | ||
image_out_path = join(output_path, image) | ||
image_out_dirpath = dirname(image_out_path) | ||
if not isdir(image_out_dirpath): | ||
os.makedirs(image_out_dirpath) | ||
shutil.move(image_in_path, image_out_path) | ||
|
||
|
||
def print_redirects(paths): | ||
"""Prints redirects we need to make on the ReadTheDocs backend with the form "input -> output". | ||
Moving the file /learning/features/viewports/viewports.rst to /tutorials/viewports/viewports.rst | ||
Requires the following redirect: | ||
/learning/features/viewports/viewports.html -> /tutorials/viewports/viewports.html | ||
""" | ||
redirects = "" | ||
project_root_path = find_project_root_path(paths[0]) | ||
out_path_relative = relpath(args.output_path, project_root_path) | ||
for document in paths: | ||
in_path_relative = relpath(document, project_root_path) | ||
in_directory, filename_rst = split(in_path_relative) | ||
filename_html = filename_rst.rsplit(".rst", 1)[0] + ".html" | ||
|
||
in_path = join(in_directory, filename_html) | ||
out_path = join(out_path_relative, filename_html) | ||
redirects += in_path + " -> " + out_path + "\n" | ||
print(redirects) | ||
|
||
|
||
if __name__ == "__main__": | ||
args = parse_and_get_arguments() | ||
assert isdir(args.output_path) | ||
|
||
documents = [ | ||
path for path in args.documents if isfile(path) and path.endswith(".rst") | ||
] | ||
move_documents(documents, args.output_path) | ||
print_redirects(documents) |