Skip to content

Commit bbedc0a

Browse files
committed
Generate reST/ref docs from python or stub files
1 parent 8b09b1f commit bbedc0a

File tree

7 files changed

+135
-7
lines changed

7 files changed

+135
-7
lines changed

buildconfig/stubs/gen_stubs.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,8 @@ def get_all(mod: Any):
131131
f.write(misc_stubs)
132132

133133
for mod, items in pygame_all_imports.items():
134+
if mod == "pygame":
135+
mod = "."
134136
if len(items) <= 4:
135137
# try to write imports in a single line if it can fit the line limit
136138
import_items = (f"{string} as {string}" for string in items)

buildconfig/stubs/pygame/__init__.pyi

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
# A script to auto-generate locals.pyi, constants.pyi and __init__.pyi typestubs
33
# IMPORTANT NOTE: Do not edit this file by hand!
44

5-
from pygame import (
5+
from . import (
66
display as display,
77
draw as draw,
88
event as event,

docs/reST/conf.py

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
# All configuration values have a default; values that are commented out
1111
# serve to show the default.
1212

13-
import sys, os
13+
import sys, os, pathlib
1414

1515
# If extensions (or modules to document with autodoc) are in another directory,
1616
# add these directories to sys.path here. If the directory is relative to the
@@ -23,11 +23,22 @@
2323

2424
# Add any Sphinx extension module names here, as strings. They can be extensions
2525
# coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
26-
extensions = ['sphinx.ext.autodoc', 'sphinx.ext.doctest',
27-
'sphinx.ext.coverage', 'ext.headers', 'ext.boilerplate',
28-
'ext.customversion', 'ext.edit_on_github']
26+
extensions = ['autoapi.extension', 'ext.headers', 'ext.boilerplate',
27+
'ext.customversion', 'ext.edit_on_github', 'ext.documenters']
2928

3029

30+
autoapi_dirs = [
31+
pathlib.Path(os.path.abspath(".")).parent.parent / 'buildconfig' / 'stubs' / 'pygame' / '',
32+
pathlib.Path(os.path.abspath(".")).parent.parent / 'src_py' / '',
33+
]
34+
35+
autoapi_options = ['members', 'undoc-members']
36+
autoapi_ignore = ["*controller.py", "*_sdl2/window.py", "*freetype.py", "*ftfont.py", "*__pyinstaller*", "*__init__.py", "*__briefcase*"]
37+
autoapi_generate_api_docs = False
38+
autodoc_typehints = 'none'
39+
suppress_warnings = ['autoapi.python_import_resolution']
40+
autodoc_member_order = 'bysource'
41+
3142
# Add any paths that contain templates here, relative to this directory.
3243
templates_path = ['_templates']
3344

docs/reST/ext/documenters.py

Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
import autoapi
2+
import autoapi.documenters
3+
from autoapi._objects import PythonClass
4+
5+
6+
def build_signatures(object):
7+
name = object.short_name
8+
9+
if isinstance(object, PythonClass):
10+
if object.constructor is not None:
11+
object = object.constructor
12+
object.obj["return_annotation"] = name
13+
object.obj["overloads"] = [
14+
(arg, name) for arg, _ in object.obj["overloads"]
15+
]
16+
17+
else:
18+
for child in object.children:
19+
if child.short_name == "__new__":
20+
object = child
21+
break
22+
23+
if object is None:
24+
return
25+
26+
sigs = [(object.obj["args"], object.obj["return_annotation"])]
27+
sigs.extend(object.obj["overloads"])
28+
29+
for args, ret in sigs:
30+
arg_string = ""
31+
for modifier, arg_name, _, default in args:
32+
modifier = modifier or ""
33+
arg_name = arg_name or ""
34+
default = default or ""
35+
36+
if default:
37+
default = "=" + default
38+
arg_string += f", {modifier}{arg_name}{default}"
39+
40+
if arg_string:
41+
arg_string = arg_string[2:]
42+
43+
if ret.count("[") > 2 or ret.count(",") > 3:
44+
ret = "..."
45+
46+
yield f"| :sg:`{name}({arg_string}) -> {ret}`"
47+
48+
49+
class AutopgDocumenter(autoapi.documenters.AutoapiDocumenter):
50+
def format_signature(self, **kwargs):
51+
return ""
52+
53+
def get_doc(self, encoding=None, ignore=1):
54+
if self.object.docstring:
55+
return super().get_doc(encoding, ignore)
56+
57+
# If we don't already have docs, check if a python implementation exists of this
58+
# module and return its docstring if it does
59+
python_object = self.env.autoapi_all_objects.get(
60+
self.object.id.replace("pygame", "src_py"), None
61+
)
62+
if python_object is not None:
63+
return [python_object.docstring.splitlines()]
64+
65+
return [""]
66+
67+
def process_doc(self, docstrings: list[str]):
68+
for docstring in docstrings:
69+
if not docstring:
70+
continue
71+
72+
yield f"| :sl:`{docstring[0]}`"
73+
74+
if "args" in self.object.obj or hasattr(self.object, "constructor"):
75+
yield from build_signatures(self.object)
76+
else:
77+
annotation = self.object.obj.get("annotation", None)
78+
if annotation is not None:
79+
if annotation.count("[") > 2 or annotation.count(",") > 3:
80+
annotation = "..."
81+
yield f"| :sg:`{self.object.short_name} -> {annotation}`"
82+
83+
yield from docstring[1:]
84+
85+
yield ""
86+
87+
88+
def setup(app):
89+
names = [
90+
"function",
91+
"property",
92+
"decorator",
93+
"class",
94+
"method",
95+
"data",
96+
"attribute",
97+
"module",
98+
"exception",
99+
]
100+
101+
for name in names:
102+
capitalized = name.capitalize()
103+
app.add_autodocumenter(
104+
type(
105+
f"Autopg{capitalized}Documenter",
106+
(
107+
AutopgDocumenter,
108+
getattr(autoapi.documenters, f"Autoapi{capitalized}Documenter"),
109+
),
110+
{"objtype": f"pg{name}"},
111+
)
112+
)

docs/reST/ext/indexer.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,6 @@ def collect_document_info(app, doctree):
6565

6666

6767
class CollectInfo(Visitor):
68-
6968
"""Records the information for a document"""
7069

7170
desctypes = {
@@ -74,6 +73,7 @@ class CollectInfo(Visitor):
7473
"exception",
7574
"class",
7675
"attribute",
76+
"property",
7777
"method",
7878
"staticmethod",
7979
"classmethod",

pyproject.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ requires = [
5959
"ninja<=1.11.1.1",
6060
"cython<=3.0.11",
6161
"sphinx<=7.2.6",
62+
"autoapi<=3.3.2",
6263
]
6364
build-backend = 'mesonpy'
6465

src_py/camera.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,9 @@ def _pre_init_placeholder_varargs(*_, **__):
5656

5757

5858
class _PreInitPlaceholderCamera(AbstractCamera):
59-
__init__ = _pre_init_placeholder_varargs
59+
def __init__(self, *args, **kwargs):
60+
_pre_init_placeholder()
61+
6062
start = _pre_init_placeholder_varargs
6163
stop = _pre_init_placeholder_varargs
6264
get_controls = _pre_init_placeholder_varargs

0 commit comments

Comments
 (0)