From b61c1e6a5739e5aabbea1dc8cd70297bb666827b Mon Sep 17 00:00:00 2001 From: Hassan Abouelela Date: Mon, 21 Feb 2022 12:58:40 +0000 Subject: Update how we auto-generate docs --- docs/utils.py | 117 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 117 insertions(+) create mode 100644 docs/utils.py (limited to 'docs/utils.py') diff --git a/docs/utils.py b/docs/utils.py new file mode 100644 index 00000000..8bc69ccd --- /dev/null +++ b/docs/utils.py @@ -0,0 +1,117 @@ +"""Utilities used in generating docs.""" + +import ast +import importlib +import inspect +import typing +from pathlib import Path + +PROJECT_ROOT = Path(__file__).parent.parent + + +def linkcode_resolve(source_url: str, domain: str, info: dict[str, str]) -> typing.Optional[str]: + """ + Function called by linkcode to get the URL for a given resource. + + See for more details: + https://www.sphinx-doc.org/en/master/usage/extensions/linkcode.html#confval-linkcode_resolve + """ + if domain != "py": + raise Exception("Unknown domain passed to linkcode function.") + + symbol_name = info["fullname"] + + module = importlib.import_module(info["module"]) + + symbol = [module] + for name in symbol_name.split("."): + symbol.append(getattr(symbol[-1], name)) + symbol_name = name + + try: + lines, start = inspect.getsourcelines(symbol[-1]) + end = start + len(lines) + except TypeError: + # Find variables by parsing the ast + source = ast.parse(inspect.getsource(symbol[-2])) + while isinstance(source.body[0], ast.ClassDef): + source = source.body[0] + + for ast_obj in source.body: + if isinstance(ast_obj, ast.Assign): + names = [] + for target in ast_obj.targets: + if isinstance(target, ast.Tuple): + names.extend([name.id for name in target.elts]) + else: + names.append(target.id) + + if symbol_name in names: + start, end = ast_obj.lineno, ast_obj.end_lineno + break + else: + raise Exception(f"Could not find symbol `{symbol_name}` in {module.__name__}.") + + _, offset = inspect.getsourcelines(symbol[-2]) + if offset != 0: + offset -= 1 + start += offset + end += offset + + file = Path(inspect.getfile(module)).relative_to(PROJECT_ROOT).as_posix() + + url = f"{source_url}/{file}#L{start}" + if end != start: + url += f"-L{end}" + + return url + + +def cleanup() -> None: + """Remove unneeded autogenerated doc files, and clean up others.""" + included = __get_included() + + for file in (PROJECT_ROOT / "docs" / "output").iterdir(): + if file.name in ("botcore.rst", "botcore.exts.rst") and file.name in included: + content = file.read_text(encoding="utf-8").splitlines(keepends=True) + + # Rename the extension to be less wordy + # Example: botcore.exts -> Botcore Exts + title = content[0].split()[0].strip().replace("botcore.", "").replace(".", " ").title() + title = f"{title}\n{'=' * len(title)}\n\n" + content[0:2] = title + + file.write_text("".join(content), encoding="utf-8") + + elif file.name in included: + # Clean up the submodule name so it's just the name without the top level module name + # example: `botcore.regex module` -> `regex` + lines = file.read_text(encoding="utf-8").splitlines(keepends=True) + lines[0] = lines[0].replace("module", "").strip().split(".")[-1] + "\n" + file.write_text("".join(lines)) + + else: + # These are files that have not been explicitly included in the docs via __all__ + print("Deleted file", file.name) + file.unlink() + continue + + # Take the opportunity to configure autodoc + content = file.read_text(encoding="utf-8").replace("undoc-members", "special-members") + file.write_text(content, encoding="utf-8") + + +def __get_included() -> set[str]: + """Get a list of files that should be included in the final build.""" + + def get_all_from_module(module_name: str) -> set[str]: + module = importlib.import_module(module_name) + _modules = {module.__name__ + ".rst"} + + if hasattr(module, "__all__"): + for sub_module in module.__all__: + _modules.update(get_all_from_module(sub_module)) + + return _modules + + return get_all_from_module("botcore") -- cgit v1.2.3 From aed1a762d97863b136e51e5d3a95d1333492dc72 Mon Sep 17 00:00:00 2001 From: Chris Lovering Date: Thu, 24 Feb 2022 16:20:07 +0000 Subject: Include utils package in doc cleanup funciton --- docs/utils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'docs/utils.py') diff --git a/docs/utils.py b/docs/utils.py index 8bc69ccd..6afbeec0 100644 --- a/docs/utils.py +++ b/docs/utils.py @@ -72,7 +72,7 @@ def cleanup() -> None: included = __get_included() for file in (PROJECT_ROOT / "docs" / "output").iterdir(): - if file.name in ("botcore.rst", "botcore.exts.rst") and file.name in included: + if file.name in ("botcore.rst", "botcore.exts.rst", "botcore.utils.rst") and file.name in included: content = file.read_text(encoding="utf-8").splitlines(keepends=True) # Rename the extension to be less wordy -- cgit v1.2.3 From 222025fdaab4cc66427590dc053730a09a5af24e Mon Sep 17 00:00:00 2001 From: Chris Lovering Date: Thu, 24 Feb 2022 17:44:07 +0000 Subject: Update GHA Docs Build To Match Pyproject Updates the command in GH actions to match the command in pyproject to generate the correct output. Kaizens a small fix in clean up. --- .github/workflows/docs.yaml | 2 +- docs/utils.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'docs/utils.py') diff --git a/.github/workflows/docs.yaml b/.github/workflows/docs.yaml index 8018d63c..a01ea58f 100644 --- a/.github/workflows/docs.yaml +++ b/.github/workflows/docs.yaml @@ -31,7 +31,7 @@ jobs: - run: pip install six - name: Generate AutoDoc References - run: sphinx-apidoc -o docs/output botcore -fe + run: sphinx-apidoc -o docs/output botcore -feM - name: Generate HTML Site run: sphinx-build -nW -j auto -b html docs docs/build diff --git a/docs/utils.py b/docs/utils.py index 6afbeec0..76b3e098 100644 --- a/docs/utils.py +++ b/docs/utils.py @@ -79,7 +79,7 @@ def cleanup() -> None: # Example: botcore.exts -> Botcore Exts title = content[0].split()[0].strip().replace("botcore.", "").replace(".", " ").title() title = f"{title}\n{'=' * len(title)}\n\n" - content[0:2] = title + content = title, *content[3:] file.write_text("".join(content), encoding="utf-8") -- cgit v1.2.3