|
| 1 | +""" |
| 2 | +Create placeholder files for all other files in the codebase. |
| 3 | +
|
| 4 | +This script is run by mkdocs-gen-files when the documentation is built and |
| 5 | +creates placeholder files for all other files in the codebase. This is done so |
| 6 | +that the documentation site can link to all files in the codebase, even if they |
| 7 | +aren't part of the documentation proper. |
| 8 | +
|
| 9 | +If the files are binary, they are copied as-is (e.g. for images), otherwise a |
| 10 | +HTML redirect is created. |
| 11 | +
|
| 12 | +If the destination file already exists (either because it is a real file, or was |
| 13 | +otherwise already generated), the script will ignore the current file and |
| 14 | +continue silently. |
| 15 | +""" |
| 16 | + |
| 17 | +import subprocess |
| 18 | +from pathlib import Path |
| 19 | +from typing import TYPE_CHECKING |
| 20 | + |
| 21 | +import mkdocs_gen_files |
| 22 | +from mkdocs_gen_files.editor import FilesEditor |
| 23 | + |
| 24 | +if TYPE_CHECKING: |
| 25 | + import io |
| 26 | + |
| 27 | +EDITOR = FilesEditor.current() |
| 28 | + |
| 29 | +# These paths are relative to the project root, *not* the current file. |
| 30 | +SRC_ROOT = "." |
| 31 | +DOCS_DEST = "." |
| 32 | + |
| 33 | +# List of all files version controlled files in the SRC_ROOT |
| 34 | +ALL_FILES = sorted( |
| 35 | + map( |
| 36 | + Path, |
| 37 | + subprocess.check_output(["git", "ls-files", SRC_ROOT]) # noqa: S603, S607 |
| 38 | + .decode("utf-8") |
| 39 | + .splitlines(), |
| 40 | + ), |
| 41 | +) |
| 42 | + |
| 43 | + |
| 44 | +def is_binary(buffer: bytes) -> bool: |
| 45 | + """ |
| 46 | + Determine whether the given buffer is binary or not. |
| 47 | +
|
| 48 | + The check is done by attempting to decode the buffer as UTF-8. If this |
| 49 | + succeeds, the buffer is not binary. If it fails, the buffer is binary. |
| 50 | +
|
| 51 | + The entire buffer will be checked, therefore if checking whether a file is |
| 52 | + binary, only the start of the file should be passed. |
| 53 | +
|
| 54 | + Args: |
| 55 | + buffer: |
| 56 | + The buffer to check. |
| 57 | +
|
| 58 | + Returns: |
| 59 | + True if the buffer is binary, False otherwise. |
| 60 | + """ |
| 61 | + try: |
| 62 | + buffer.decode("utf-8") |
| 63 | + except UnicodeDecodeError: |
| 64 | + return True |
| 65 | + else: |
| 66 | + return False |
| 67 | + |
| 68 | + |
| 69 | +for source_path in ALL_FILES: |
| 70 | + if not source_path.is_file(): |
| 71 | + continue |
| 72 | + if source_path.parts[0] in ["docs"]: |
| 73 | + continue |
| 74 | + |
| 75 | + dest_path = Path(DOCS_DEST, source_path) |
| 76 | + |
| 77 | + if str(dest_path) in EDITOR.files: |
| 78 | + continue |
| 79 | + |
| 80 | + fi: "io.IOBase" |
| 81 | + with Path(source_path).open("rb") as fi: |
| 82 | + buf = fi.read(2048) |
| 83 | + |
| 84 | + if is_binary(buf): |
| 85 | + if source_path.stat().st_size < 16 * 2**20: |
| 86 | + # Copy the file only if it's less than 16MB. |
| 87 | + with Path(source_path).open("rb") as fi, mkdocs_gen_files.open( |
| 88 | + dest_path, |
| 89 | + "wb", |
| 90 | + ) as fd: |
| 91 | + fd.write(fi.read()) |
| 92 | + else: |
| 93 | + # File is too big, create a redirect. |
| 94 | + url = ( |
| 95 | + "https://github.com" |
| 96 | + "/pact-foundation/pact-python" |
| 97 | + "/raw" |
| 98 | + "/develop" |
| 99 | + f"/{source_path}" |
| 100 | + ) |
| 101 | + with mkdocs_gen_files.open(dest_path, "w", encoding="utf-8") as fd: |
| 102 | + fd.write(f'<meta http-equiv="refresh" content="0; url={url}">') |
| 103 | + fd.write(f"# Redirecting to {url}...") |
| 104 | + fd.write(f"[Click here if you are not redirected]({url})") |
| 105 | + |
| 106 | + mkdocs_gen_files.set_edit_path( |
| 107 | + dest_path, |
| 108 | + f"https://github.com/pact-foundation/pact-python/edit/develop/{source_path}", |
| 109 | + ) |
| 110 | + |
| 111 | + else: |
| 112 | + with Path(source_path).open("r", encoding="utf-8") as fi, mkdocs_gen_files.open( |
| 113 | + dest_path, |
| 114 | + "w", |
| 115 | + encoding="utf-8", |
| 116 | + ) as fd: |
| 117 | + fd.write(fi.read()) |
0 commit comments