Skip to content

API


MkDocGenerator


The MkDocGenerator generates the documentation with the links to the source code.

Parameters:

Name Type Description Default
Utilities class

[description]

required
BuilderMkDoc class

Builder class of the abstract methods and property of MkDocGenerator.

required

generate: None property readonly

The property generate of MkDocGenerator creates the final markdown files.

Example: How to use

>>> from pathlib import Path
# Import mkdocstrings-sourcelink
>>> from mkdocstrings_sourcelink import MkDocGenerator
# Define the dictionary for the documentation
>>> pages = {
    "Documentation": {
        "auto_generator.md": [
            "mkdocstrings_sourcelink.auto_generator.MkDocGenerator.__init__",
            "mkdocstrings_sourcelink.auto_generator.MkDocGenerator.render_to_markdown",
            "mkdocstrings_sourcelink.auto_generator.MkDocGenerator.initialize_generate",
            "mkdocstrings_sourcelink.auto_generator.MkDocGenerator.generate_docs",
            "mkdocstrings_sourcelink.auto_generator.MkDocGenerator.generate_static",
            "mkdocstrings_sourcelink.auto_generator.MkDocGenerator.generate",
        ]
    },
    "Tools": {
        "toolbox.md": [
            "mkdocstrings_sourcelink.toolbox.Utilities.insert_in_file",
            "mkdocstrings_sourcelink.toolbox.Utilities.element_to_mkdocstrings",
            "mkdocstrings_sourcelink.toolbox.Utilities.make_source_link",
            "mkdocstrings_sourcelink.toolbox.Utilities.make_title",
            "mkdocstrings_sourcelink.toolbox.Utilities.import_object",
            "mkdocstrings_sourcelink.toolbox.Utilities.return_as_Path",
        ],
    },
}
# Define the dictionary for the importing existing markdown files.
>>> markdown_files = {
    "HOME": {"index.md": ["../README.md"]},
    "CONTRIBUTING": {"contributing.md": ["../CONTRIBUTING.md"]},
    "LICENSE": {"license.md": ["../LICENSE"]},
}
>>> root = Path(__file__).resolve().parents[1]
# Make use of the generate poperty of MkDocGenerator
>>> MkDocGenerator(
    root / "docs" / "src",
    pages,
    "https://github.com/AI2Business/mkdocstrings-sourcelink/blob/main",
    markdown_files=markdown_files,
    underline_title=True,
    source=":material-github::material-source-branch:",
).generate
>>> ...

__init__(self, dest_dir, documentation, project_url=None, template_dir=None, example_dir=None, markdown_files=None, titles_size='#', underline_title=False, source='**source code**') special

Generates the documentation via MkDocGenerator with the links to the source.

Parameters:

Name Type Description Default
dest_dir Union[str, pathlib.Path]

Destination of the generated documentation.

required
documentation Dict[str, Dict[str, List[str]]]

A nested dictionary with the page title, the page filename, and the functions /classes / methods names of the page. The dictionary should look like: pages = {'page_title':{'filename.md': ['package.module.function']}}.

required
project_url Union[str, Dict[str, str]]

The URL, where the project is hosted and where it should be linked to (including branch and storage).

None
template_dir Union[str, pathlib.Path]

Directory of template files. If template has to be automatically filled out, then the keyword {{autogenerated}} has to be used.

None
example_dir Union[str, pathlib.Path]

Directory of example files, especially suitable for Jupyter-Notebooks.

None
markdown_files Dict[str, Dict[str, List[str]]]

A nested dictionary with the page title, the page filename, and the link to already existing markdown files like README.md or LICENSE. The dictionary should look like: pages = {'page_title':{'filename.md': ['existing_file.md']}}.

None
titles_size str

Defines the initial title size for the headings, which are scaled down by the factor of one "#".

'#'
underline_title bool

Underline titles of classes, functions, and methods.

False
source str

Name of the source link.

'**source code**'

About documentation

In terms of linking to the project_url, it has to be separated between specific and general linking. If functions or method has to be separately linked, then each module of the class Documentation has to be called individually like:

    pages = {
        "Documentation": {
            "auto_generator.md": [
                "mkdocstrings_sourcelink.auto_generator.MkDocGenerator.__init__",
                "mkdocstrings_sourcelink.auto_generator.MkDocGenerator.render_to_markdown",
                "mkdocstrings_sourcelink.auto_generator.MkDocGenerator.initialize_generate",
                "mkdocstrings_sourcelink.auto_generator.MkDocGenerator.generate_docs",
                "mkdocstrings_sourcelink.auto_generator.MkDocGenerator.generate_static",
                "mkdocstrings_sourcelink.auto_generator.MkDocGenerator.generate",
            ]
        }
    }
If functions or method has to be generally linked, then just call the class Documentation is enough. It will be only generated one single link to the start of the class.
    pages = {
        "Documentation": {
            "auto_generator.md": [
                "mkdocstrings_sourcelink.auto_generator.MkDocGenerator",
        }
    }
For more information, please check: mkdocstrings pawamoy/mkdocstrings

About source

Instead of using a string for source = "**source code**", icons can be used instead or as combination of string + icon(s) like.

    source = ":material-github::material-source-branch: source-code"
In case of using material-icons, please check https://pictogrammers.github.io/@mdi/font/5.4.55/ and replace mdl by material.

About project_url

Keep in mind, that the name of the branch like master, main, or dev, as well as, the name of the storage like blob for GitHub has to be included.

Source code in mkdocstrings_sourcelink/auto_generator.py
def __init__(
    self,
    dest_dir: Union[str, Path],
    documentation: Dict[str, Dict[str, List[str]]],
    project_url: Union[str, Dict[str, str]] = None,
    template_dir: Union[str, Path] = None,
    example_dir: Union[str, Path] = None,
    markdown_files: Dict[str, Dict[str, List[str]]] = None,
    titles_size: str = "#",
    underline_title: bool = False,
    source: str = "**source code**",
) -> None:
    """Generates the documentation via `MkDocGenerator` with the links to the source.

    Args:
        dest_dir (Union[str, Path]): Destination of the generated documentation.
        documentation (Dict[str, Dict[str, List[str]]], optional): A nested dictionary with the
             page title, the page filename, and the functions /classes / methods names of the
             page. The dictionary should look like:
             `pages = {'page_title':{'filename.md': ['package.module.function']}}`.
        project_url (Union[str, Dict[str, str]], optional): The URL, where the project is
             hosted and where it should be linked to (including branch and storage).
        template_dir (Union[str, Path], optional): Directory of template files. If template has
             to be automatically filled out, then the keyword **{{autogenerated}}** has to be
             used.
        example_dir (Union[str, Path], optional): Directory of example files, especially
             suitable for `Jupyter-Notebooks`.
        markdown_files (Dict[str, Dict[str, List[str]]], optional): A nested dictionary with
             the page title, the page filename, and the link to already existing markdown files
             like **README.md** or **LICENSE**. The dictionary should look like:
             `pages = {'page_title':{'filename.md': ['existing_file.md']}}`.
        titles_size (str, optional): Defines the initial title size for the headings, which are
             scaled down by the factor of one "#".
        underline_title (bool, optional): Underline titles of classes, functions, and methods.
        source (str, optional): Name of the source link.

    !!! info "About *documentation*"
        In terms of linking to the project_url, it has to be separated between *specific* and
         *general* linking. If functions or method has to be separately linked, then each
         module of the class `Documentation` has to be called individually like:
        ```python
            pages = {
                "Documentation": {
                    "auto_generator.md": [
                        "mkdocstrings_sourcelink.auto_generator.MkDocGenerator.__init__",
                        "mkdocstrings_sourcelink.auto_generator.MkDocGenerator.render_to_markdown",
                        "mkdocstrings_sourcelink.auto_generator.MkDocGenerator.initialize_generate",
                        "mkdocstrings_sourcelink.auto_generator.MkDocGenerator.generate_docs",
                        "mkdocstrings_sourcelink.auto_generator.MkDocGenerator.generate_static",
                        "mkdocstrings_sourcelink.auto_generator.MkDocGenerator.generate",
                    ]
                }
            }
        ```
        If functions or method has to be generally linked, then just call the class
         `Documentation` is enough. It will be only generated one single link to the start of
          the class.
          ```python
              pages = {
                  "Documentation": {
                      "auto_generator.md": [
                          "mkdocstrings_sourcelink.auto_generator.MkDocGenerator",
                  }
              }
          ```
        For more information, please check: **mkdocstrings**
        https://github.com/pawamoy/mkdocstrings

    !!! tip "About *source*"
        Instead of using a string for `source = "**source code**"`, icons can be used instead
         or as combination of string + icon(s) like.
        ```python
            source = ":material-github::material-source-branch: source-code"
        ```
        In case of using material-icons, please check https://pictogrammers.github.io/@mdi/font/5.4.55/
        and replace `mdl` by `material`.

    !!! warning "About *project_url*"
        Keep in mind, that the name of the branch like *master*, *main*, or *dev*, as well as,
         the name of the storage like *blob* for GitHub has to be included.
    """
    self.dest_dir = Path(dest_dir)
    self.documentation = documentation
    self.project_url = project_url
    self.template_dir = Utilities.return_as_Path(template_dir)
    self.example_dir = Utilities.return_as_Path(example_dir)
    self.markdown_files = markdown_files
    self.titles_size = titles_size
    self.underline_title = underline_title
    self.source = source

generate_docs(self)

Generated dynamic documentation based on calling the elements via dictionary.

Source code in mkdocstrings_sourcelink/auto_generator.py
def generate_docs(self) -> None:
    """Generated *dynamic* documentation based on calling the elements via dictionary."""
    for title, documentation in self.documentation.items():
        markdown_text = f"{self.titles_size} {title}\n\n---\n\n"
        for file_path, elements in documentation.items():
            markdown_text += "".join(
                self.render_to_markdown(element) for element in elements
            )
        Utilities.insert_in_file(markdown_text, self.dest_dir.joinpath(file_path))

generate_static(self)

Generate static documentation based on existing markdown files.

Source code in mkdocstrings_sourcelink/auto_generator.py
def generate_static(self) -> None:
    """Generate *static* documentation based on existing markdown files."""
    if self.markdown_files:
        for _, markdown_files in self.markdown_files.items():
            markdown_text = ""
            for file_path, elements in markdown_files.items():
                markdown_text += "".join(
                    Path(element).read_text() for element in elements
                )
            Utilities.insert_in_file(
                markdown_text, self.dest_dir.joinpath(file_path)
            )

initialize_generate(self)

Initialization of the auto documentation generatorion.

  1. Firs removing a possible existing target directory (dest_dir).
  2. Copy templates from the template directory the target directory(dest_dir).
  3. Copy example from the example directory the target directory (dest_dir).
Source code in mkdocstrings_sourcelink/auto_generator.py
def initialize_generate(self) -> None:
    """Initialization of the auto documentation generatorion.

    1. Firs removing a possible existing target directory (`dest_dir`).
    2. Copy templates from the template directory the target directory(`dest_dir`).
    3. Copy example from the example directory the target directory (`dest_dir`).
    """
    if self.dest_dir.exists():
        print(f"Cleaning up existing sources directory '{self.dest_dir}'.")
        shutil.rmtree(self.dest_dir)

    if self.template_dir:
        print(
            f"...copying existing sources directory '{self.template_dir}' to '{self.dest_dir}'."
        )
        shutil.copytree(self.template_dir, self.dest_dir)

    if self.example_dir:
        print(
            f"...copying existing sources directory '{self.example_dir}' to '{self.dest_dir}'."
        )
        shutil.copytree(self.example_dir, self.dest_dir)

render_to_markdown(self, element)

Rendering the element path to mkdocstrings.

Parameters:

Name Type Description Default
element str

String of they python class, function, or method, which has to be converted to a string in the mkdocstrings format.

required

Returns:

Type Description
str

str: Return of the initial string which looks like mkdocstrings_sourcelink.auto_generator.MkDocGenerator.__init__ into a markdown conformed string.

Source code in mkdocstrings_sourcelink/auto_generator.py
def render_to_markdown(self, element: str) -> str:
    """Rendering the element path to mkdocstrings.

    Args:
        element (str): String of they python class, function, or method, which has to be
             converted to a string in the mkdocstrings format.

    Returns:
        str: Return of the initial string which looks like
             `mkdocstrings_sourcelink.auto_generator.MkDocGenerator.__init__` into a markdown
             conformed string.
    """
    object_ = Utilities.import_object(element)
    subblocks = []
    if self.project_url:
        subblocks.append(
            Utilities.make_source_link(object_, self.project_url, self.source)
        )

    subblocks.append(
        Utilities.make_title(object_, self.titles_size, self.underline_title)
    )
    subblocks.append(Utilities.element_to_mkdocstrings(element, self.titles_size))
    return "\n\n".join(subblocks) + "\n\n"

Utilities


The Utilities build the mkdocstrings and generate the hyperlinks to the source code.

Parameters:

Name Type Description Default
AbstractUtilities class

Builder class of the abstract staticmethods of Utilities.

required

element_to_mkdocstrings(element, titles_size) staticmethod

Converts point separated string into the mkdocstrings format.

For converting the elements to mkdocstrings, the element will added ::: in front of the element string. In addition to that, the the new mkdocstrings will get subheadings.

Parameters:

Name Type Description Default
element str

String of they python class, function, or method, which has to be converted to a string in the mkdocstrings format.

required
titles_size str

Current title size in the style of '#', which defines the headings.

required

Returns:

Type Description
str

str: String of they python class, function, or method, which is converted to a string in the mkdocstrings format.

Source code in mkdocstrings_sourcelink/toolbox.py
@staticmethod
def element_to_mkdocstrings(element: str, titles_size: str) -> str:
    """Converts point separated string into the mkdocstrings format.

    For converting the elements to mkdocstrings, the element will added **:::** in front of the
     element string. In addition to that, the the new mkdocstrings will get subheadings.

    Args:
        element (str): String of they python class, function, or method, which has to be
             converted to a string in the mkdocstrings format.
        titles_size (str): Current title size in the style of '#', which defines the headings.

    Returns:
        str: String of they python class, function, or method, which is converted to a string
             in the mkdocstrings format.
    """
    return f"##{titles_size} :::{element}\n"

import_object(element) staticmethod

Import an object like class, function, or method from a string.

Parameters:

Name Type Description Default
element str

String of class, function, or method, which should be converted to an object.

required

Returns:

Type Description
object

object: Class, function, or method object for the giving element.

Source code in mkdocstrings_sourcelink/toolbox.py
@staticmethod
def import_object(element: str) -> object:
    """Import an object like class, function, or method from a string.

    Args:
        element (str): String of class, function, or method, which should be converted to an
             object.

    Returns:
        object: Class, function, or method object for the giving element.
    """
    last_object_got = None
    seen_names = []
    for name in element.split("."):
        seen_names.append(name)
        try:
            last_object_got = importlib.import_module(".".join(seen_names))
        except ModuleNotFoundError:
            last_object_got = getattr(last_object_got, name)

    return last_object_got

insert_in_file(markdown_text, file_path) staticmethod

Insert the markdown formatted text into a new or existing file.

Parameters:

Name Type Description Default
markdown_text str

Text as string, which follows the markdown format.

required
file_path Path

Filename and path as Path object.

required

Exceptions:

Type Description
RuntimeError

If {{autogenerated}} is not provided in a template file, it will cause a a RuntimeError.

Source code in mkdocstrings_sourcelink/toolbox.py
@staticmethod
def insert_in_file(markdown_text: str, file_path: Path) -> None:
    """Insert the markdown formatted text into a new or existing file.

    Args:
        markdown_text (str): Text as string, which follows the markdown format.
        file_path (Path): Filename and path as Path object.

    Raises:
        RuntimeError: If {{autogenerated}} is not provided in a template file, it will cause a
            a **RuntimeError**.
    """
    if file_path.exists():
        template = file_path.read_text(encoding="utf-8")
        if "{{autogenerated}}" not in template:
            raise RuntimeError(
                f"Template found for {file_path} but missing "
                f"{{autogenerated}} tag."
            )
        markdown_text = template.replace("{{autogenerated}}", markdown_text)
        print(f"...inserting autogenerated content into template:{file_path}")
    else:
        print(f"...creating new page with autogenerated content:{file_path}")
    file_path.parent.mkdir(parents=True, exist_ok=True)
    file_path.write_text(markdown_text, encoding="utf-8")

Make a source link to the code basis including the linestart.

Parameters:

Name Type Description Default
cls classmethod

Convert a function to be a class method.

required
project_url Union[str, Dict[str, str]]

URL to the repository like GitHub AI2Business/mkdocstrings-sourcelink.

required
source str

Name or sticker name for rendering the link to the source.

'**source code**'

Returns:

Type Description
str

str: Hyperlink in html format with link to the repository.

About source

Instead of using a string for source = "**source code**", icons can be used instead or as combination of string + icon(s) like.

    source = ":material-github::material-source-branch: source-code"
In case of using material-icons, please check https://pictogrammers.github.io/@mdi/font/5.4.55/ and replace mdl by material.

Source code in mkdocstrings_sourcelink/toolbox.py
@staticmethod
def make_source_link(
    cls: classmethod,
    project_url: Union[str, Dict[str, str]],
    source: str = "**source code**",
) -> str:
    """Make a source link to the code basis including the linestart.

    Args:
        cls (classmethod): Convert a function to be a class method.
        project_url (Union[str, Dict[str, str]]): URL to the repository like GitHub
             https://github.com/AI2Business/mkdocstrings-sourcelink/.
        source (str, optional): Name or sticker name for rendering the link to the
             source.

    Returns:
        str: Hyperlink in html format with link to the repository.

    !!! tip "About *source*"
        Instead of using a string for `source = "**source code**"`, icons can be used instead
         or as combination of string + icon(s) like.
        ```python
            source = ":material-github::material-source-branch: source-code"
        ```
        In case of using material-icons, please check https://pictogrammers.github.io/@mdi/font/5.4.55/
        and replace `mdl` by `material`.
    """
    if isinstance(project_url, dict):
        if isinstance(cls, property):
            base_module = cls.fget.__module__.split(".")[0]
        else:
            base_module = cls.__module__.split(".")[0]
        project_url = project_url[base_module]

    if isinstance(cls, property):
        path = cls.fget.__module__.replace(".", "/")
        line = inspect.getsourcelines(cls.fget)[-1]
    else:
        path = cls.__module__.replace(".", "/")
        line = inspect.getsourcelines(cls)[-1]

    return (
        f'<span style="float:right;">'
        f"[{source}]({project_url}/{path}.py#L{line})"
        f"</span>"
    )

make_title(cls, titles_size, underline_title) staticmethod

Make the title of the class, function, or method.

Parameters:

Name Type Description Default
cls classmethod

Convert a function to be a class method. In case of class properties fget is used to read out the name of the module.

required
titles_size str

Current title size in the style of '#', which defines the headings.

required

Returns:

Type Description
str

str: The name of the class, function, or method in a markdown conformed title.

Source code in mkdocstrings_sourcelink/toolbox.py
@staticmethod
def make_title(cls: classmethod, titles_size: str, underline_title: bool) -> str:
    """Make the title of the class, function, or method.

    Args:
        cls (classmethod): Convert a function to be a class method. In case of class properties
             `fget` is used to read out the name of the module.
        titles_size (str): Current title size in the style of '#', which defines the headings.

    Returns:
        str: The name of the class, function, or method in a markdown conformed title.
    """
    title_underline = "\n---\n" if underline_title else "\n"
    if isinstance(cls, property):
        return f"#{titles_size} {cls.fget.__name__}{title_underline}"
    return f"#{titles_size} {cls.__name__}{title_underline}"

return_as_Path(path=None) staticmethod

Converts strings to Path of pathlib.

Parameters:

Name Type Description Default
path str

String of a filename.

None

Returns:

Type Description
Optional[pathlib.Path]

Optional[Path]: Path object of the initial filename.

Source code in mkdocstrings_sourcelink/toolbox.py
@staticmethod
def return_as_Path(path: str = None) -> Optional[Path]:
    """Converts strings to Path of pathlib.

    Args:
        path (str, optional): String of a filename.

    Returns:
        Optional[Path]: Path object of the initial filename.
    """
    if path:
        return Path(path)
    return None

Last update: November 9, 2021