aboutsummaryrefslogtreecommitdiffstats
path: root/docs
diff options
context:
space:
mode:
authorGravatar Hassan Abouelela <[email protected]>2021-12-06 21:20:27 +0400
committerGravatar GitHub <[email protected]>2021-12-06 21:20:27 +0400
commitcfe4d495f7e9581fe58576cdf5e5dd9a490e52ed (patch)
treea3919899b8adbbed5822d40e2ab7dacfa084ab9c /docs
parentMerge pull request #1 from python-discord/mbaruh/setup (diff)
parentMove Doc Dependencies Into Dev Section (diff)
Merge pull request #2 from python-discord/docs-buildv1.1.0
Documentation
Diffstat (limited to 'docs')
-rw-r--r--docs/README.md45
-rw-r--r--docs/_static/changelog.css11
-rw-r--r--docs/_static/changelog.js37
-rw-r--r--docs/_static/logo.css3
-rw-r--r--docs/changelog.rst10
-rw-r--r--docs/conf.py228
-rw-r--r--docs/index.rst27
7 files changed, 361 insertions, 0 deletions
diff --git a/docs/README.md b/docs/README.md
new file mode 100644
index 00000000..06c5a739
--- /dev/null
+++ b/docs/README.md
@@ -0,0 +1,45 @@
+# Docs
+Meta information about this project's documentation.
+
+Table of contents:
+- [Building the docs](#Building)
+- [Writing docstrings](#Docstrings)
+- [Writing a changelog](#Changelog)
+
+
+## Building
+To build the docs, you can use the following task:
+```shell
+poetry run task docs
+```
+
+The output will be in the [`/docs/build`](.) directory.
+
+Additionally, there are two helper tasks: `apidoc` and `builddoc`.
+`apidoc` is responsible for calling autodoc and generating docs from docstrings.
+`builddoc` generates the HTML site, and should be called after apidoc.
+
+Neither of these two tasks needs to be manually called, as the `docs` task calls both.
+
+
+## Docstrings
+To have your code properly added to the generated docs, you need to do a couple of things:
+1. Write your code with annotations.
+2. [Write your docstring, using the Google docstring format][google]
+
+Refer to the [sphinx documentation][docstring-sections] for more information.
+
+
+[google]: https://sphinxcontrib-napoleon.readthedocs.io/en/latest/example_google.html
+[docstring-sections]: https://www.sphinx-doc.org/en/master/usage/extensions/napoleon.html#docstring-sections
+
+
+## Changelog
+Each change requires an entry in the [Changelog](./changelog.rst).
+
+Refer to the [Releases][releases] documentation for more information on the exact format and content of entries
+You can use [this site][releases] to get the PR number you'll use for your entry.
+
+
+[next]: https://ichard26.github.io/next-pr-number/?owner=python-discord&name=bot-core
+[releases]: https://releases.readthedocs.io/en/latest/concepts.html
diff --git a/docs/_static/changelog.css b/docs/_static/changelog.css
new file mode 100644
index 00000000..343792a1
--- /dev/null
+++ b/docs/_static/changelog.css
@@ -0,0 +1,11 @@
+[data-theme='dark'] #changelog .dark,
+[data-theme='light'] #changelog .light,
+[data-theme='auto'] #changelog .light {
+ display: inline;
+}
+
+[data-theme='dark'] #changelog .light,
+[data-theme='light'] #changelog .dark,
+[data-theme='auto'] #changelog .dark {
+ display: none;
+}
diff --git a/docs/_static/changelog.js b/docs/_static/changelog.js
new file mode 100644
index 00000000..f72d025c
--- /dev/null
+++ b/docs/_static/changelog.js
@@ -0,0 +1,37 @@
+/** Update the changelog colors in dark mode */
+
+const changelog = document.getElementById("changelog");
+
+function updateEntryColor(entry) {
+ const line = entry.lastChild;
+ const lightColorSpan = line.childNodes.item(1);
+ const darkColorSpan = lightColorSpan.cloneNode(true);
+
+ line.insertBefore(darkColorSpan, lightColorSpan);
+
+ lightColorSpan.classList.add("light");
+ darkColorSpan.classList.add("dark");
+
+ let color;
+ switch (darkColorSpan.textContent) {
+ case "Feature":
+ color = "#5BF38E";
+ break;
+ case "Support":
+ color = "#55A5E7";
+ break;
+ case "Bug":
+ color = "#E14F4F";
+ break;
+ default:
+ color = null;
+ }
+
+ darkColorSpan.style["color"] = color;
+}
+
+if (changelog !== null) {
+ for (let collection of changelog.getElementsByClassName("simple")) {
+ Array.from(collection.children).forEach(updateEntryColor);
+ }
+}
diff --git a/docs/_static/logo.css b/docs/_static/logo.css
new file mode 100644
index 00000000..a9c28e5c
--- /dev/null
+++ b/docs/_static/logo.css
@@ -0,0 +1,3 @@
+.sidebar-logo {
+ border-radius: 50%;
+}
diff --git a/docs/changelog.rst b/docs/changelog.rst
new file mode 100644
index 00000000..4954b59c
--- /dev/null
+++ b/docs/changelog.rst
@@ -0,0 +1,10 @@
+.. See docs for details on formatting your entries
+ https://releases.readthedocs.io/en/latest/concepts.html
+
+
+Changelog
+=========
+
+- :support:`2` Autogenerated docs.
+- :feature:`2` Regex utility.
+- :support:`1` Core package, poetry, and linting CI.
diff --git a/docs/conf.py b/docs/conf.py
new file mode 100644
index 00000000..4ab831d3
--- /dev/null
+++ b/docs/conf.py
@@ -0,0 +1,228 @@
+# Configuration file for the Sphinx documentation builder.
+# https://www.sphinx-doc.org/en/master/usage/configuration.html
+
+import ast
+import importlib
+import inspect
+import sys
+import typing
+from pathlib import Path
+
+import git
+import tomli
+from sphinx.application import Sphinx
+
+# -- Project information -----------------------------------------------------
+
+project = "Bot Core"
+copyright = "2021, Python Discord"
+author = "Python Discord"
+
+PROJECT_ROOT = Path(__file__).parent.parent
+REPO_LINK = "https://github.com/python-discord/bot-core"
+SOURCE_FILE_LINK = f"{REPO_LINK}/blob/{git.Repo(PROJECT_ROOT).commit().hexsha}"
+
+sys.path.insert(0, str(PROJECT_ROOT.absolute()))
+
+# The full version, including alpha/beta/rc tags
+release = version = tomli.loads(
+ (PROJECT_ROOT / "pyproject.toml").read_text(encoding="utf-8")
+)["tool"]["poetry"]["version"]
+
+# -- General configuration ---------------------------------------------------
+
+add_module_names = False
+
+# Add any Sphinx extension module names here, as strings. They can be
+# extensions coming with Sphinx (named "sphinx.ext.*") or your custom
+# ones.
+extensions = [
+ "sphinx.ext.extlinks",
+ "sphinx.ext.autodoc",
+ "sphinx.ext.todo",
+ "sphinx.ext.napoleon",
+ "sphinx_autodoc_typehints",
+ "releases",
+ "sphinx.ext.linkcode",
+ "sphinx.ext.githubpages",
+]
+
+# Add any paths that contain templates here, relative to this directory.
+templates_path = ["_templates"]
+
+# List of patterns, relative to source directory, that match files and
+# directories to ignore when looking for source files.
+# This pattern also affects html_static_path and html_extra_path.
+exclude_patterns = []
+
+
+# -- Options for HTML output -------------------------------------------------
+
+# The theme to use for HTML and HTML Help pages. See the documentation for
+# a list of builtin themes.
+#
+html_theme = "furo"
+
+html_theme_options = {
+ "light_css_variables": {
+ "color-api-name": "var(--color-link)",
+ },
+}
+
+# Add any paths that contain custom static files (such as style sheets) here,
+# relative to this directory. They are copied after the builtin static files,
+# so a file named "default.css" will overwrite the builtin "default.css".
+html_static_path = ["_static"]
+html_title = f"{project} v{version}"
+html_short_title = project
+
+html_logo = "https://raw.githubusercontent.com/python-discord/branding/main/logos/logo_full/logo_full.min.svg"
+html_favicon = html_logo
+
+html_css_files = [
+ "changelog.css",
+ "logo.css",
+]
+
+html_js_files = [
+ "changelog.js",
+]
+
+
+# -- Autodoc cleanup ---------------------------------------------------------
+# Clean up the output generated by autodoc to produce a nicer documentation tree
+# This is kept in a function to avoid polluting the namespace
+def __cleanup() -> None:
+ for file in (PROJECT_ROOT / "docs" / "output").iterdir():
+ if file.name == "modules.rst":
+ # We only have one module, so this is redundant
+ # Remove it and flatten out the tree
+ file.unlink()
+
+ elif file.name == "botcore.rst":
+ # We want to bring the submodule name to the top, and remove anything that's not a submodule
+ result = ""
+ for line in file.read_text(encoding="utf-8").splitlines(keepends=True):
+ if ".." not in line and result == "":
+ # We have not reached the first submodule, this is all filler
+ continue
+ elif "Module contents" in line:
+ # We have parsed all the submodules, so let's skip the redudant module name
+ break
+ result += line
+
+ result = "Botcore\n=======\n\n" + result
+ file.write_text(result, encoding="utf-8")
+
+ else:
+ # 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()
+ lines[0] = lines[0].replace("botcore.", "").replace("module", "").strip()
+
+ # Take the opportunity to configure autodoc
+ lines = "\n".join(lines).replace("undoc-members", "special-members")
+ file.write_text(lines, encoding="utf-8")
+
+
+__cleanup()
+
+
+def skip(*args) -> bool:
+ """Things that should be skipped by the autodoc generation."""
+ name = args[2]
+ would_skip = args[4]
+
+ if name in (
+ "__weakref__",
+ ):
+ return True
+ return would_skip
+
+
+def setup(app: Sphinx) -> None:
+ """Add extra hook-based autodoc configuration."""
+ app.connect("autodoc-skip-member", skip)
+
+
+# -- Extension configuration -------------------------------------------------
+
+# -- Options for todo extension ----------------------------------------------
+
+# If true, `todo` and `todoList` produce output, else they produce nothing.
+todo_include_todos = True
+
+
+# -- Options for napoleon extension ------------------------------------------
+napoleon_google_docstring = True
+napoleon_numpy_docstring = False
+napoleon_attr_annotations = True
+
+
+# -- Options for releases extension ------------------------------------------
+releases_github_path = REPO_LINK.removeprefix("https://github.com/")
+
+
+# -- Options for extlinks extension ------------------------------------------
+extlinks = {
+ "repo-file": (f"{REPO_LINK}/blob/main/%s", "repo-file %s")
+}
+
+
+# -- Options for the linkcode extension --------------------------------------
+def linkcode_resolve(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_FILE_LINK}/{file}#L{start}"
+ if end != start:
+ url += f"-L{end}"
+
+ return url
diff --git a/docs/index.rst b/docs/index.rst
new file mode 100644
index 00000000..e7c25ef1
--- /dev/null
+++ b/docs/index.rst
@@ -0,0 +1,27 @@
+.. Generated by sphinx-quickstart on Thu Dec 2 01:21:15 2021.
+
+Bot Core Project Documentation
+==============================
+
+
+Reference
+====================================
+
+.. toctree::
+ :maxdepth: 4
+ :caption: Modules:
+
+ output/botcore
+
+.. toctree::
+ :caption: Other:
+
+ changelog
+
+
+Extras
+==================
+
+* :ref:`genindex`
+* :ref:`search`
+* :repo-file:`Information <docs/README.md>`