Skip to content
This repository has been archived by the owner on Jan 2, 2023. It is now read-only.

Support for splitting {{autogenerated}} tags to allow modular template files #89

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 41 additions & 10 deletions keras_autodoc/autogen.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import shutil
import pathlib
from inspect import getdoc, isclass, getfullargspec
from typing import Dict, Union, List
from inspect import getdoc, isclass
from typing import Dict, Union, List, get_type_hints

from .docstring import process_docstring
from .examples import copy_examples
Expand All @@ -19,6 +19,8 @@ class DocumentationGenerator:
are lists of strings, functions /classes / methods names
with dotted access to the object. For example,
`pages = {'my_file.md': ['keras.layers.Dense']}` is valid.
Values can also be dictionaries, introducing an extra level to map
custom tags to lists of elements to be documented.
project_url: The url pointing to the module directory of your project on
GitHub. This will be used to make a `[Sources]` link.
template_dir: Where to put the markdown files which will be copied and
Expand Down Expand Up @@ -69,6 +71,9 @@ def generate(self, dest_dir):
# Arguments

dest_dir: Where to put the resulting markdown files.

# Raises
TypeError: if elements are not specified as list or dict of lists.
"""
dest_dir = pathlib.Path(dest_dir)
print("Cleaning up existing sources directory.")
Expand All @@ -80,10 +85,21 @@ def generate(self, dest_dir):
shutil.copytree(self.template_dir, dest_dir)

for file_path, elements in self.pages.items():
markdown_text = ''
for element in elements:
markdown_text += self._render(element)
utils.insert_in_file(markdown_text, dest_dir / file_path)
if isinstance(elements, list):
self._render_list_and_insert(elements, dest_dir / file_path)
elif isinstance(elements, dict):
for tag, grouped_elements in elements.items():
if isinstance(grouped_elements, list):
self._render_list_and_insert(
grouped_elements, dest_dir / file_path, tag)
else:
raise TypeError(
"Expected list of elements to be documented, is of type {}: {}"
.format(type(grouped_elements), grouped_elements))
else:
raise TypeError(
"Expected list of elements to be documented, is of type {}: {}"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
"Expected list of elements to be documented, is of type {}: {}"
"Expected list or dict of elements to be documented, is of type {}: {}"

.format(type(elements), elements))

if self.examples_dir is not None:
copy_examples(self.examples_dir, dest_dir / "examples")
Expand Down Expand Up @@ -111,6 +127,12 @@ def _render(self, element):

return self._render_from_object(object_, signature_override)

def _render_list_and_insert(self, element_list, file_path, tag="autogenerated"):
markdown_text = ''
for element in element_list:
markdown_text += self._render(element)
utils.insert_in_file(markdown_text, file_path, tag)

def _render_from_object(self, object_, signature_override: str):
subblocks = []
if self.project_url is not None:
Expand All @@ -124,14 +146,23 @@ def _render_from_object(self, object_, signature_override: str):

docstring = getdoc(object_)
if docstring:
docstring = self.process_docstring(
docstring, getfullargspec(object_).annotations
)
if isclass(object_):
type_hints = get_type_hints(object_.__init__)
else:
type_hints = get_type_hints(object_)
docstring = self.process_docstring(docstring, type_hints)
subblocks.append(docstring)
return "\n\n".join(subblocks) + '\n\n----\n\n'

def _fill_aliases(self, extra_aliases):
for list_elements in self.pages.values():
for elements in self.pages.values():
if isinstance(elements, dict):
# collect all lists of elements to be documented
list_elements = []
for element in elements.values():
list_elements += element
else:
list_elements = elements
for element_as_str in list_elements:
element = utils.import_object(element_as_str)
if not isclass(element):
Expand Down
21 changes: 15 additions & 6 deletions keras_autodoc/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,18 +12,27 @@ def count_leading_spaces(s):
return 0


def insert_in_file(markdown_text, file_path):
def insert_in_file(markdown_text, file_path, tag):
"""Save module page.

Either insert content into existing page,
or create page otherwise."""
or create page otherwise.

# Arguments
markdown_text: text to be inserted in file.
file_path: path to file to insert text in.
tag: a tag name without parenthesis to replace with content.
"""
tag_par = "{{" + tag + "}}"
if file_path.exists():
template = file_path.read_text(encoding="utf-8")
if "{{autogenerated}}" not in template:
if tag_par not in template:
raise RuntimeError(f"Template found for {file_path} but missing "
f"{{autogenerated}} tag.")
markdown_text = template.replace("{{autogenerated}}", markdown_text)
print("...inserting autogenerated content into template:", file_path)
f"{tag_par} tag.")
markdown_text = template.replace(tag_par, markdown_text)
print(
f"...inserting autogenerated content for tag {tag_par} into template:",
file_path)
else:
print("...creating new page with autogenerated content:", file_path)
os.makedirs(file_path.parent, exist_ok=True)
Expand Down