123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109 |
- 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)
|