Skip to content

Commit 633d8e0

Browse files
committed
Initial commit
0 parents  commit 633d8e0

File tree

12 files changed

+363
-0
lines changed

12 files changed

+363
-0
lines changed

.github/workflows/dist.yml

+38
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
---
2+
name: dist
3+
4+
on: [push, pull_request]
5+
6+
jobs:
7+
check:
8+
runs-on: ubuntu-latest
9+
10+
steps:
11+
- uses: actions/checkout@v2
12+
- uses: actions/setup-python@v1
13+
with:
14+
python-version: 3.8
15+
- name: Black
16+
run: |
17+
pip install black
18+
black --check --diff .
19+
20+
publish:
21+
runs-on: ubuntu-latest
22+
needs: [check]
23+
if: github.event_name == 'push' && startsWith(github.event.ref, 'refs/tags')
24+
25+
steps:
26+
- uses: actions/checkout@v2
27+
- uses: actions/setup-python@v1
28+
with:
29+
python-version: 3.8
30+
- run: pip install wheel
31+
32+
- name: Build packages
33+
run: python setup.py sdist bdist_wheel
34+
- name: Publish to PyPI
35+
uses: pypa/gh-action-pypi-publish@master
36+
with:
37+
user: __token__
38+
password: ${{ secrets.pypi_password }}

.gitignore

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
*.pyc
2+
__pycache__
3+
*.egg-info
4+
5+
.vscode
6+
7+
/build
8+
/dist

README.md

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
robotpy-sphinx-plugin
2+
=====================
3+
4+
Common sphinx tooling for RobotPy projects.
5+
6+
TODO docs for this repo

pyproject.toml

+22
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
[build-system]
2+
requires = ['setuptools>=43', 'wheel', 'setuptools_scm==3.3.3']
3+
4+
[tool.black]
5+
target-version = ['py36']
6+
exclude = '''
7+
(
8+
/(
9+
\.eggs # exclude a few common directories in the
10+
| \.git # root of the project
11+
| \.hg
12+
| \.mypy_cache
13+
| \.nox
14+
| \.tox
15+
| \.venv
16+
| _build
17+
| buck-out
18+
| build
19+
| dist
20+
)/
21+
)
22+
'''

robotpy_sphinx/__init__.py

Whitespace-only changes.

robotpy_sphinx/all.py

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
"""
2+
Includes sphinx extensions useful for all robotpy projects
3+
"""
4+
5+
6+
def setup(app):
7+
from . import pybind11_fixer
8+
9+
app.setup_extension(pybind11_fixer.__name__)
10+
app.setup_extension("sphinx_autodoc_typehints")
11+
app.setup_extension("sphinx_automodapi.smart_resolver")

robotpy_sphinx/pybind11_fixer.py

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import sphinx.addnodes
2+
3+
4+
def process_child(node):
5+
6+
if isinstance(node, sphinx.addnodes.desc_parameterlist) and node.children:
7+
first_child = node.children[0]
8+
if first_child.children and str(first_child.children[0]).startswith("self:"):
9+
node.children = node.children[1:]
10+
11+
for child in node.children:
12+
process_child(child)
13+
14+
15+
def doctree_read(app, doctree):
16+
for child in doctree.children:
17+
process_child(child)
18+
19+
20+
def setup(app):
21+
app.connect("doctree-read", doctree_read)

robotpy_sphinx/regen.py

+141
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,141 @@
1+
#!/usr/bin/env python3
2+
"""
3+
A custom documentation generator because sphinx-apidoc doesn't quite do
4+
what I want it to. The autosummary thing is really close to what I want.
5+
However, the documentation for how to use it is lacking.
6+
7+
This is designed to generate docs for our flat import structure in a
8+
manner that is friendly to the readthedocs theme.
9+
"""
10+
11+
import fnmatch
12+
import inspect
13+
import os
14+
import sys
15+
16+
from os.path import abspath, join, dirname, exists
17+
from .utils import write_if_changed
18+
19+
from sphinx_automodapi.utils import find_mod_objs
20+
21+
mod_doc = """
22+
%(header)s
23+
24+
%(fnlink)s
25+
26+
.. autosummary::
27+
%(names)s
28+
29+
.. toctree::
30+
:hidden:
31+
32+
%(files)s
33+
34+
"""
35+
36+
cls_doc = """
37+
%(header)s
38+
39+
.. autoclass:: %(package_name)s.%(cls_name)s
40+
:members:
41+
:undoc-members:
42+
:show-inheritance:
43+
"""
44+
45+
46+
def _heading(name, c):
47+
return "%s\n%s" % (name, c * len(name))
48+
49+
50+
def gen_package(root: str, package_name: str, exclude=None):
51+
"""
52+
Writes rst files describing a package
53+
"""
54+
55+
if not exclude:
56+
exclude = []
57+
58+
found = find_mod_objs(package_name)
59+
60+
docdir = abspath(join(root, package_name))
61+
fnrst = abspath(join(root, package_name, "functions.rst"))
62+
pkgrst = abspath(join(root, f"{package_name}.rst"))
63+
64+
old_files = {}
65+
if exists(docdir):
66+
for fname in os.listdir(docdir):
67+
old_files[join(docdir, fname)] = True
68+
else:
69+
os.mkdir(docdir)
70+
71+
classes = []
72+
functions = []
73+
74+
for name, _, obj in zip(*found):
75+
76+
excluded = False
77+
for pattern in exclude:
78+
if fnmatch.fnmatch(name, pattern):
79+
excluded = True
80+
break
81+
82+
if excluded:
83+
continue
84+
85+
if inspect.isclass(obj):
86+
fname = join(docdir, f"{name}.rst")
87+
write_if_changed(
88+
fname,
89+
cls_doc
90+
% {
91+
"header": _heading(name, "-"),
92+
"package_name": package_name,
93+
"cls_name": name,
94+
},
95+
)
96+
97+
old_files.pop(fname, None)
98+
classes.append(name)
99+
100+
elif inspect.isroutine(obj):
101+
functions.append(name)
102+
103+
classes = sorted(classes)
104+
functions = sorted(functions)
105+
106+
# Create toctree
107+
108+
names = ["%s.%s" % (package_name, clsname) for clsname in classes]
109+
files = ["%s/%s" % (package_name, clsname) for clsname in classes]
110+
fnlink = ""
111+
112+
if functions:
113+
files.insert(0, f"{package_name}/functions")
114+
fnlink = f":doc:`{package_name} functions <{package_name}/functions>`"
115+
116+
functions_doc = _heading(f"{package_name} functions", "-").split("\n")
117+
for fn in functions:
118+
functions_doc.extend(
119+
["", f".. autofunction:: {package_name}.{fn}" "",]
120+
)
121+
122+
write_if_changed(fnrst, "\n".join(functions_doc))
123+
old_files.pop(fnrst, None)
124+
125+
write_if_changed(
126+
pkgrst,
127+
mod_doc
128+
% {
129+
"header": _heading(package_name + " Package", "="),
130+
"fnlink": fnlink,
131+
"module": package_name,
132+
"names": "\n ".join(names),
133+
"files": "\n ".join(files),
134+
},
135+
)
136+
137+
old_files.pop(pkgrst, None)
138+
139+
# delete any files that were not written, since this is an autogenerated directory
140+
for fname in old_files.keys():
141+
os.unlink(fname)

robotpy_sphinx/sidebar.py

+68
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
#
2+
# This file generates the sidebar/toctree for all RobotPy projects and should
3+
# be copied to each project when it is updated
4+
#
5+
6+
import os
7+
import os.path
8+
import toml
9+
10+
from .utils import write_if_changed
11+
import urllib.request
12+
13+
14+
def generate_sidebar(
15+
conf, this_project, url, out="_sidebar.inc.rst", cfg="_sidebar.toml", lang="en"
16+
):
17+
"""
18+
Call this from your sphinx project's conf.py::
19+
20+
generate_sidebar(globals(), "name", "url")
21+
22+
Your toplevel index.rst should have something like this:
23+
24+
.. include:: _sidebar.rst.inc
25+
"""
26+
27+
# determine 'latest' or 'stable'
28+
force_dl = conf["on_rtd"]
29+
do_gen = os.environ.get("SIDEBAR", None) == "1" or conf["on_rtd"]
30+
version = conf["rtd_version"]
31+
32+
lines = ["", ".. DO NOT MODIFY! THIS PAGE IS AUTOGENERATED!", ""]
33+
34+
def toctree(name):
35+
lines.extend([".. toctree::", f" :caption: {name}", " :maxdepth: 2", ""])
36+
37+
def endl():
38+
lines.append("")
39+
40+
def write(project, desc, link):
41+
if project == this_project:
42+
args = desc, link
43+
elif not do_gen:
44+
return
45+
else:
46+
project_url = data["projects"][project]
47+
args = (
48+
desc,
49+
f"{project_url}/{lang}/{version}/{link}.html",
50+
)
51+
52+
lines.append(" %s <%s>" % args)
53+
54+
if force_dl or not os.path.exists(cfg):
55+
urllib.request.urlretrieve(url, cfg)
56+
57+
with open(cfg) as fp:
58+
data = toml.load(fp)
59+
60+
for tt in data["toctree"]:
61+
toctree(tt["name"])
62+
63+
for item in tt["items"]:
64+
write(item["p"], item["k"], item["v"])
65+
66+
endl()
67+
68+
write_if_changed("_sidebar.rst.inc", "\n".join(lines))

robotpy_sphinx/utils.py

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
def write_if_changed(fname, contents):
2+
3+
try:
4+
with open(fname, "r") as fp:
5+
old_contents = fp.read()
6+
except:
7+
old_contents = ""
8+
9+
if old_contents != contents:
10+
with open(fname, "w") as fp:
11+
fp.write(contents)

setup.cfg

+32
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
[metadata]
2+
name = robotpy-sphinx-plugin
3+
description = Common Sphinx tooling for RobotPy projects
4+
long_description = file: README.md
5+
long_description_content_type = text/markdown
6+
author = Dustin Spicuzza
7+
author_email = [email protected]
8+
url = https://github.com/robotpy/robotpy-sphinx-plugin
9+
license = BSD-3-Clause
10+
classifiers =
11+
Development Status :: 5 - Production/Stable
12+
Intended Audience :: Developers
13+
License :: OSI Approved :: BSD License
14+
Programming Language :: Python :: 3 :: Only
15+
Programming Language :: Python :: 3.6
16+
Programming Language :: Python :: 3.7
17+
Programming Language :: Python :: 3.8
18+
Topic :: Software Development
19+
20+
[options]
21+
zip_safe = False
22+
include_package_data = True
23+
packages = find:
24+
install_requires =
25+
setuptools >= 43
26+
setuptools_scm == 3.3.3
27+
sphinx-autodoc-typehints
28+
sphinx-automodapi
29+
toml
30+
setup_requires =
31+
setuptools_scm
32+
python_requires = >=3.6

setup.py

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
#!/usr/bin/env python3
2+
3+
from setuptools import setup
4+
5+
setup(use_scm_version=True)

0 commit comments

Comments
 (0)