-
Notifications
You must be signed in to change notification settings - Fork 137
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
MkDocs is a popular tool in the Python ecosystem to generate documentation. It has support for parsing Python docstrings in order to generate API documentation quite easily. Signed-off-by: JP-Ellis <josh@jpellis.me>
- Loading branch information
Showing
9 changed files
with
469 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,55 @@ | ||
name: Generate and Publish Docs | ||
|
||
on: | ||
push: | ||
|
||
env: | ||
STABLE_PYTHON_VERSION: "3.11" | ||
PYTEST_ADDOPTS: --color=yes | ||
|
||
jobs: | ||
build: | ||
name: Build docs | ||
|
||
runs-on: ubuntu-latest | ||
|
||
steps: | ||
- name: Checkout code | ||
uses: actions/checkout@v4 | ||
with: | ||
fetch-depth: 0 | ||
|
||
- name: Set up Python | ||
uses: actions/setup-python@v4 | ||
with: | ||
python-version: ${{ env.STABLE_PYTHON_VERSION }} | ||
|
||
- name: Install Hatch | ||
run: pip install --upgrade hatch | ||
|
||
- name: Build docs | ||
run: | | ||
hatch run mkdocs build | ||
- name: Upload artifact | ||
uses: actions/upload-pages-artifact@v2 | ||
with: | ||
path: site | ||
|
||
publish: | ||
name: Publish docs | ||
|
||
needs: build | ||
runs-on: ubuntu-latest | ||
permissions: | ||
contents: read | ||
pages: write | ||
id-token: write | ||
environment: | ||
name: github-pages | ||
url: ${{ steps.deployment.outputs.page_url }} | ||
|
||
steps: | ||
- name: Deploy to GitHub Pages | ||
id: deployment | ||
uses: actions/deploy-pages@v2 |
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
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,5 @@ | ||
- [Home](README.md) | ||
- [Changelog](CHANGELOG.md) | ||
- [Contributing](CONTRIBUTING.md) | ||
- [Pact](pact/) | ||
- [Examples](examples/) |
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,62 @@ | ||
""" | ||
Script to merge Markdown documentation from the main codebase into the docs. | ||
This script is run by mkdocs-gen-files when the documentation is built and | ||
imports Markdown documentation from the main codebase so that it can be included | ||
in the documentation site. For example, a Markdown file located at | ||
`some/path/foo.md` will be treated as if it was located at | ||
`docs/some/path/foo.md` without the need for symlinks or copying the file. | ||
If the destination file already exists (either because it is a real file, or was | ||
otherwise already generated), the script will raise a RuntimeError. | ||
""" | ||
|
||
import subprocess | ||
import sys | ||
from pathlib import Path | ||
|
||
import mkdocs_gen_files | ||
from mkdocs_gen_files.editor import FilesEditor | ||
|
||
EDITOR = FilesEditor.current() | ||
|
||
# These paths are relative to the project root, *not* the current file. | ||
SRC_ROOT = "." | ||
DOCS_DEST = "." | ||
|
||
# List of all files version controlled files in the SRC_ROOT | ||
ALL_FILES = sorted( | ||
map( | ||
Path, | ||
subprocess.check_output(["git", "ls-files", SRC_ROOT]) # noqa: S603, S607 | ||
.decode("utf-8") | ||
.splitlines(), | ||
), | ||
) | ||
|
||
|
||
for source_path in filter(lambda p: p.suffix == ".md", ALL_FILES): | ||
if source_path.parts[0] == "docs": | ||
continue | ||
dest_path = Path(DOCS_DEST, source_path) | ||
|
||
if str(dest_path) in EDITOR.files: | ||
print( # noqa: T201 | ||
f"Unable to copy {source_path} to {dest_path} because the file already" | ||
" exists at the destination.", | ||
file=sys.stderr, | ||
) | ||
msg = f"File {dest_path} already exists." | ||
raise RuntimeError(msg) | ||
|
||
with Path(source_path).open("r", encoding="utf-8") as fi, mkdocs_gen_files.open( | ||
dest_path, | ||
"w", | ||
encoding="utf-8", | ||
) as fd: | ||
fd.write(fi.read()) | ||
|
||
mkdocs_gen_files.set_edit_path( | ||
dest_path, | ||
f"https://github.com/pact-foundation/pact-python/edit/develop/{source_path}", | ||
) |
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,117 @@ | ||
""" | ||
Create placeholder files for all other files in the codebase. | ||
This script is run by mkdocs-gen-files when the documentation is built and | ||
creates placeholder files for all other files in the codebase. This is done so | ||
that the documentation site can link to all files in the codebase, even if they | ||
aren't part of the documentation proper. | ||
If the files are binary, they are copied as-is (e.g. for images), otherwise a | ||
HTML redirect is created. | ||
If the destination file already exists (either because it is a real file, or was | ||
otherwise already generated), the script will ignore the current file and | ||
continue silently. | ||
""" | ||
|
||
import subprocess | ||
from pathlib import Path | ||
from typing import TYPE_CHECKING | ||
|
||
import mkdocs_gen_files | ||
from mkdocs_gen_files.editor import FilesEditor | ||
|
||
if TYPE_CHECKING: | ||
import io | ||
|
||
EDITOR = FilesEditor.current() | ||
|
||
# These paths are relative to the project root, *not* the current file. | ||
SRC_ROOT = "." | ||
DOCS_DEST = "." | ||
|
||
# List of all files version controlled files in the SRC_ROOT | ||
ALL_FILES = sorted( | ||
map( | ||
Path, | ||
subprocess.check_output(["git", "ls-files", SRC_ROOT]) # noqa: S603, S607 | ||
.decode("utf-8") | ||
.splitlines(), | ||
), | ||
) | ||
|
||
|
||
def is_binary(buffer: bytes) -> bool: | ||
""" | ||
Determine whether the given buffer is binary or not. | ||
The check is done by attempting to decode the buffer as UTF-8. If this | ||
succeeds, the buffer is not binary. If it fails, the buffer is binary. | ||
The entire buffer will be checked, therefore if checking whether a file is | ||
binary, only the start of the file should be passed. | ||
Args: | ||
buffer: | ||
The buffer to check. | ||
Returns: | ||
True if the buffer is binary, False otherwise. | ||
""" | ||
try: | ||
buffer.decode("utf-8") | ||
except UnicodeDecodeError: | ||
return True | ||
else: | ||
return False | ||
|
||
|
||
for source_path in ALL_FILES: | ||
if not source_path.is_file(): | ||
continue | ||
if source_path.parts[0] in ["docs"]: | ||
continue | ||
|
||
dest_path = Path(DOCS_DEST, source_path) | ||
|
||
if str(dest_path) in EDITOR.files: | ||
continue | ||
|
||
fi: "io.IOBase" | ||
with Path(source_path).open("rb") as fi: | ||
buf = fi.read(2048) | ||
|
||
if is_binary(buf): | ||
if source_path.stat().st_size < 16 * 2**20: | ||
# Copy the file only if it's less than 16MB. | ||
with Path(source_path).open("rb") as fi, mkdocs_gen_files.open( | ||
dest_path, | ||
"wb", | ||
) as fd: | ||
fd.write(fi.read()) | ||
else: | ||
# File is too big, create a redirect. | ||
url = ( | ||
"https://github.com" | ||
"/pact-foundation/pact-python" | ||
"/raw" | ||
"/develop" | ||
f"/{source_path}" | ||
) | ||
with mkdocs_gen_files.open(dest_path, "w", encoding="utf-8") as fd: | ||
fd.write(f'<meta http-equiv="refresh" content="0; url={url}">') | ||
fd.write(f"# Redirecting to {url}...") | ||
fd.write(f"[Click here if you are not redirected]({url})") | ||
|
||
mkdocs_gen_files.set_edit_path( | ||
dest_path, | ||
f"https://github.com/pact-foundation/pact-python/edit/develop/{source_path}", | ||
) | ||
|
||
else: | ||
with Path(source_path).open("r", encoding="utf-8") as fi, mkdocs_gen_files.open( | ||
dest_path, | ||
"w", | ||
encoding="utf-8", | ||
) as fd: | ||
fd.write(fi.read()) |
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,70 @@ | ||
""" | ||
Script used by mkdocs-gen-files to generate documentation for Pact Python. | ||
The script is run by mkdocs-gen-files when the documentation is built in order | ||
to generate documentation from Python docstrings. | ||
""" | ||
import subprocess | ||
from pathlib import Path | ||
from typing import Union | ||
|
||
import mkdocs_gen_files | ||
|
||
|
||
def process_python(src: str, dest: Union[str, None] = None) -> None: | ||
""" | ||
Process the Python files in the given directory. | ||
The source directory is relative to the root of the repository, and only | ||
Python files which are version controlled are processed. The generated | ||
documentation may optionally written to a different directory. | ||
""" | ||
dest = dest or src | ||
|
||
# List of all files version controlled files in the SRC_ROOT | ||
files = sorted( | ||
map( | ||
Path, | ||
subprocess.check_output(["git", "ls-files", src]) # noqa: S603, S607 | ||
.decode("utf-8") | ||
.splitlines(), | ||
), | ||
) | ||
files = filter(lambda p: p.suffix == ".py", files) | ||
files = sorted(files) | ||
|
||
for source_path in files: | ||
module_path = source_path.relative_to(src).with_suffix("") | ||
doc_path = source_path.relative_to(src).with_suffix(".md") | ||
full_doc_path = Path(dest, doc_path) | ||
|
||
parts = [src, *module_path.parts] | ||
|
||
# Skip __main__ modules | ||
if parts[-1] == "__main__": | ||
continue | ||
|
||
# The __init__ modules are implicit in the directory structure. | ||
if parts[-1] == "__init__": | ||
parts = parts[:-1] | ||
full_doc_path = full_doc_path.parent / "README.md" | ||
|
||
if full_doc_path.exists(): | ||
with mkdocs_gen_files.open(full_doc_path, "a", encoding="utf-8") as fd: | ||
python_identifier = ".".join(parts) | ||
print("# " + parts[-1], file=fd) | ||
print("::: " + python_identifier, file=fd) | ||
else: | ||
with mkdocs_gen_files.open(full_doc_path, "w", encoding="utf-8") as fd: | ||
python_identifier = ".".join(parts) | ||
print("# " + parts[-1], file=fd) | ||
print("::: " + python_identifier, file=fd) | ||
|
||
mkdocs_gen_files.set_edit_path( | ||
full_doc_path, | ||
f"https://github.com/pact-foundation/pact-python/edit/master/pact/{module_path}.py", | ||
) | ||
|
||
|
||
process_python("pact") | ||
process_python("examples") |
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,4 @@ | ||
extend = "../../pyproject.toml" | ||
ignore = [ | ||
"INP001", # Forbid implicit namespaces | ||
] |
Oops, something went wrong.