Skip to content

Commit 93fb571

Browse files
committed
Basic tests for single page rendering
1 parent ecd47ea commit 93fb571

File tree

25 files changed

+697
-190
lines changed

25 files changed

+697
-190
lines changed

autoapi/extension.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -271,7 +271,7 @@ def setup(app):
271271
app.add_config_value("autoapi_python_class_content", "class", "html")
272272
app.add_config_value("autoapi_generate_api_docs", True, "html")
273273
app.add_config_value("autoapi_prepare_jinja_env", None, "html")
274-
app.add_config_value("autoapi_single_page_level", "module", "html")
274+
app.add_config_value("autoapi_own_page_level", "module", "html")
275275
app.add_autodocumenter(documenters.AutoapiFunctionDocumenter)
276276
app.add_autodocumenter(documenters.AutoapiPropertyDocumenter)
277277
app.add_autodocumenter(documenters.AutoapiDecoratorDocumenter)

autoapi/mappers/base.py

Lines changed: 29 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,20 @@
1313
from sphinx.util.osutil import ensuredir
1414
import sphinx.util.logging
1515

16-
from ..settings import API_ROOT, TEMPLATE_DIR, SINGLE_PAGE_LEVELS
16+
from ..settings import API_ROOT, TEMPLATE_DIR
1717

1818
LOGGER = sphinx.util.logging.getLogger(__name__)
19+
_OWN_PAGE_LEVELS = [
20+
"package",
21+
"module",
22+
"exception",
23+
"class",
24+
"function",
25+
"method",
26+
"property",
27+
"attribute",
28+
"data",
29+
]
1930

2031
Path = namedtuple("Path", ["absolute", "relative"])
2132

@@ -90,10 +101,15 @@ def rendered(self):
90101
return self.render()
91102

92103
def get_context_data(self):
104+
own_page_level = self.app.config.autoapi_own_page_level
105+
desired_page_level = _OWN_PAGE_LEVELS.index(own_page_level)
106+
own_page_types = set(_OWN_PAGE_LEVELS[:desired_page_level+1])
107+
93108
return {
94109
"autoapi_options": self.app.config.autoapi_options,
95110
"include_summaries": self.app.config.autoapi_include_summaries,
96111
"obj": self,
112+
"own_page_types": own_page_types,
97113
"sphinx_version": sphinx.version_info,
98114
}
99115

@@ -191,18 +207,20 @@ def _wrapped_prepare(value):
191207
if self.app.config.autoapi_prepare_jinja_env:
192208
self.app.config.autoapi_prepare_jinja_env(self.jinja_env)
193209

210+
own_page_level = self.app.config.autoapi_own_page_level
211+
desired_page_level = _OWN_PAGE_LEVELS.index(own_page_level)
212+
self.own_page_types = set(_OWN_PAGE_LEVELS[:desired_page_level+1])
213+
194214
self.url_root = url_root
195215

196216
# Mapping of {filepath -> raw data}
197217
self.paths = OrderedDict()
198218
# Mapping of {object id -> Python Object}
199-
self.objects = OrderedDict()
219+
self.objects_to_render = OrderedDict()
200220
# Mapping of {object id -> Python Object}
201221
self.all_objects = OrderedDict()
202222
# Mapping of {namespace id -> Python Object}
203223
self.namespaces = OrderedDict()
204-
# Mapping of {namespace id -> Python Object}
205-
self.top_level_objects = OrderedDict()
206224

207225
def load(self, patterns, dirs, ignore=None):
208226
"""Load objects from the filesystem into the ``paths`` dictionary."""
@@ -280,7 +298,9 @@ def add_object(self, obj):
280298
Args:
281299
obj: Instance of a AutoAPI object
282300
"""
283-
self.objects[obj.id] = obj
301+
if obj.type in self.own_page_types:
302+
self.objects_to_render[obj.id] = obj
303+
284304
self.all_objects[obj.id] = obj
285305
child_stack = list(obj.children)
286306
while child_stack:
@@ -307,75 +327,34 @@ def create_class(self, data, options=None, **kwargs):
307327
"""
308328
raise NotImplementedError
309329

310-
def output_child_rst(self, obj, obj_parent, detail_dir, single_page_level, source_suffix):
311-
312-
if not obj.display:
313-
return
314-
315-
obj_child_page_level = SINGLE_PAGE_LEVELS.index(obj.type)
316-
desired_page_level = SINGLE_PAGE_LEVELS.index(single_page_level)
317-
needs_single_page = obj_child_page_level <= desired_page_level
318-
if not needs_single_page:
319-
return
320-
321-
obj_child_rst = obj.render(
322-
needs_single_page=needs_single_page,
323-
)
324-
if not obj_child_rst:
325-
return
326-
327-
ensuredir(os.path.join(detail_dir, obj.short_name))
328-
path = os.path.join(
329-
detail_dir, obj.short_name, f"index{source_suffix}"
330-
)
331-
332-
with open(path, "wb+") as obj_child_detail_file:
333-
obj_child_detail_file.write(obj_child_rst.encode("utf-8"))
334-
335-
for obj_child in obj.children:
336-
child_detail_dir = os.path.join(detail_dir, obj.name)
337-
self.output_child_rst(obj_child, obj, child_detail_dir, single_page_level, source_suffix)
338-
339-
340330
def output_rst(self, root, source_suffix):
341-
# Evaluate which object types should render in a single page
342-
single_page_level = self.app.config.autoapi_single_page_level
343-
desired_page_level = SINGLE_PAGE_LEVELS.index(single_page_level)
344-
single_page_objects = SINGLE_PAGE_LEVELS[:desired_page_level+1]
345-
346331
for _, obj in status_iterator(
347-
self.objects.items(),
332+
self.objects_to_render.items(),
348333
colorize("bold", "[AutoAPI] ") + "Rendering Data... ",
349-
length=len(self.objects),
334+
length=len(self.objects_to_render),
350335
verbosity=1,
351336
stringify_func=(lambda x: x[0]),
352337
):
353338
if not obj.display:
354339
continue
355340

356-
rst = obj.render(single_page_objects=single_page_objects)
341+
rst = obj.render(is_own_page=True)
357342
if not rst:
358343
continue
359344

360345
detail_dir = obj.include_dir(root=root)
361346
ensuredir(detail_dir)
362347
path = os.path.join(detail_dir, f"index{source_suffix}")
363-
364348
with open(path, "wb+") as detail_file:
365349
detail_file.write(rst.encode("utf-8"))
366-
367-
for obj_child in obj.children:
368-
self.output_child_rst(obj_child, obj, detail_dir=detail_dir,
369-
single_page_level=single_page_level,
370-
source_suffix=source_suffix)
371350

372351
if self.app.config.autoapi_add_toctree_entry:
373352
self._output_top_rst(root)
374353

375354
def _output_top_rst(self, root):
376355
# Render Top Index
377356
top_level_index = os.path.join(root, "index.rst")
378-
pages = self.objects.values()
357+
pages = self.objects_to_render.values()
379358
with open(top_level_index, "wb") as top_level_file:
380359
content = self.jinja_env.get_template("index.rst")
381360
top_level_file.write(content.render(pages=pages).encode("utf-8"))

autoapi/mappers/python/mapper.py

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
PythonAttribute,
2525
PythonData,
2626
PythonException,
27+
TopLevelPythonPythonMapper,
2728
)
2829

2930
LOGGER = sphinx.util.logging.getLogger(__name__)
@@ -345,19 +346,20 @@ def map(self, options=None):
345346

346347
super().map(options)
347348

348-
parents = {obj.name: obj for obj in self.objects.values()}
349-
for obj in self.objects.values():
349+
top_level_objects = {obj.id: obj for obj in self.all_objects.values() if isinstance(obj, TopLevelPythonPythonMapper)}
350+
parents = {obj.name: obj for obj in top_level_objects.values()}
351+
for obj in self.objects_to_render.values():
350352
parent_name = obj.name.rsplit(".", 1)[0]
351353
if parent_name in parents and parent_name != obj.name:
352354
parent = parents[parent_name]
353355
attr = f"sub{obj.type}s"
354356
getattr(parent, attr).append(obj)
355357

356-
for obj in self.objects.values():
358+
for obj in top_level_objects.values():
357359
obj.submodules.sort()
358360
obj.subpackages.sort()
359361

360-
self.app.env.autoapi_objects = self.objects
362+
self.app.env.autoapi_objects = self.objects_to_render
361363
self.app.env.autoapi_all_objects = self.all_objects
362364

363365
def create_class(self, data, options=None, **kwargs):

autoapi/mappers/python/objects.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ class PythonPythonMapper(PythonMapperBase):
3838
language = "python"
3939
is_callable = False
4040
member_order = 0
41+
type: str
4142

4243
def __init__(self, obj, class_content="class", **kwargs) -> None:
4344
super().__init__(obj, **kwargs)

autoapi/settings.py

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -10,15 +10,3 @@
1010
TEMPLATE_DIR = os.path.join(SITE_ROOT, "templates")
1111

1212
API_ROOT = "autoapi"
13-
14-
SINGLE_PAGE_LEVELS = [
15-
"package",
16-
"module",
17-
"exception",
18-
"class",
19-
"function",
20-
"method",
21-
"property",
22-
"attribute",
23-
"data",
24-
]

autoapi/templates/python/class.rst

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{% if obj.display %}
2-
{% if needs_single_page %}
3-
{{ obj.short_name }}
4-
{{ "=" * obj.short_name | length }}
2+
{% if is_own_page %}
3+
{{ obj.name }}
4+
{{ "=" * obj.name | length }}
55
{% endif %}
66

77
.. py:{{ obj.type }}:: {{ obj.short_name }}{% if obj.args %}({{ obj.args }}){% endif %}
@@ -30,6 +30,7 @@
3030
{% if obj.docstring %}
3131
{{ obj.docstring|indent(3) }}
3232
{% endif %}
33+
{# TODO: Rendering of all children below this line must be conditional on own_page_types #}
3334
{% if "inherited-members" in autoapi_options %}
3435
{% set visible_classes = obj.classes|selectattr("display")|list %}
3536
{% else %}

autoapi/templates/python/data.rst

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,9 @@
11
{% if obj.display %}
2+
{% if is_own_page %}
3+
{{ obj.name }}
4+
{{ "=" * obj.name | length }}
5+
6+
{% endif %}
27
.. py:{{ obj.type }}:: {{ obj.name }}
38
{%- if obj.annotation is not none %}
49

autoapi/templates/python/function.rst

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
{% if obj.display %}
2-
{% if needs_single_page %}
3-
{{ obj.short_name }}
4-
{{ "=" * obj.short_name | length }}
5-
{% endif %}
2+
{% if is_own_page %}
3+
{{ obj.name }}
4+
{{ "=" * obj.name | length }}
65

6+
{% endif %}
77
.. py:function:: {{ obj.short_name }}({{ obj.args }}){% if obj.return_annotation is not none %} -> {{ obj.return_annotation }}{% endif %}
88
99
{% for (args, return_annotation) in obj.overloads %}

autoapi/templates/python/method.rst

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
{%- if obj.display %}
2-
{% if needs_single_page %}
3-
{{ obj.short_name }}
4-
{{ "=" * obj.short_name | length }}
5-
{% endif %}
2+
{% if is_own_page %}
3+
{{ obj.name }}
4+
{{ "=" * obj.name | length }}
65

6+
{% endif %}
77
.. py:method:: {{ obj.short_name }}({{ obj.args }}){% if obj.return_annotation is not none %} -> {{ obj.return_annotation }}{% endif %}
88
99
{% for (args, return_annotation) in obj.overloads %}

0 commit comments

Comments
 (0)