Skip to content

Getting started

When using the Pydoc-Markdown integration with Novella to make use of its Markdown pre-processing capabilities, Pydoc-Markdown comes as a plugin that provides a @pydoc and @pylink tag to insert Markdown documentation generated by Pydoc-Markdown in the corresponding places of your documentation.


When using Pipx, the recommended installation method is to inject Pydoc-Markdown later:

$ pipx install novella
$ pipx inject novella pydoc-markdown[novella]

If you manage the environment yourself, it's sufficient to install Pydoc-Markdown with the novella extra.

$ pip install pydoc-markdown[novella]


A Novella build is configured using a build.novella script. In most cases you want to rely on a template provided by Novella, such as the MkDocs template. Check out the Novella documentation to find what types of templates are available here.

template "mkdocs" {
  content_directory = "content"

action "preprocess-markdown" {
  use "pydoc"

What is happening here?

  1. The mkdocs pipeline template is applied. The content_directory is the directory that contains your MkDocs source files. It will be copied to the temporary build location alongside the mkdocs.yml file. Note that your build.novella script should sit next two these files.

Note: You should have mkdocs on your PATH and it should have the mkdocs-material theme installed (the default theme that Novella will apply if you don't specify a different one in your mkdocs.yml file or in build.novella).

  1. The preprocess-markdown action that is one of the actions created by the template is retrieved and configured further. We instruct it to make use of the "pydoc" plugin, which is implemented by Pydoc-Markdown and provides the @pydoc and {@link pydoc:} tags.


  • The content/ directory is the default so it does not need to be set explicitly and it is sufficient to write template "mkdocs" (without an empty configuration block).

  • The mkdocs template will apply a default configuration delivered with Novella to your MkDocs configuration. If you don't want this, you can configure the "mkdocs-update-config" action to disable this. Note that you can also have no MkDocs configuration file and the template will create a default file for you.

  • The pydoc tag is implemented in {@link pydoc:pydoc_markdown.novella.preprocessor.PydocTagPreprocessor}. Look it up to understand how it can be configured further.

  • The pydoc tag processor applies a heuristic to populate the default search path for your Python source code. If the directory in which the build is executed is called docs or documentation, it will default to [ "../src", ".." ], otherwise it will default to [ "src", "." ].

Using Novella tags

For example, the @cat tag is useful to inject the content of another file.

# Welcome to my Project documentation!

@cat ../../ :with slice_lines = "2:"

The @pydoc tag is the piece provided by Pydoc-Markdown itself. It uses the Class MarkdownRenderer to generate Markdown formatted API documentation of the API object you specify.

# API Documentation

@pydoc my_module.SomeClass

Build the documentation

Change into the docs/ directory where your build.novella script resides and invoke the Novella CLI. The MkDocs template exposes some command-line arguments that you can pass through the CLI, one of which is the --serve option that runs MkDocs in the server mode instead of building the documentation and writing it to disk.

$ novella --help
usage: novella [--version] [-h] [-i TEMPLATE] [-c PATH] [-d DIRECTORY]
               [-b PATH] [-r] [--dot] [--intercept ACTION] [--serve]
               [--port PORT] [--site-dir PATH] [--base-url URL]

  --version             show program's version number and exit
  -h, --help            Show this help output.
                        Create a `build.novella` file initialized from a
                        template. Available templates are: "mkdocs", "hugo"
  -c PATH, --config-file PATH
                        The configuration file to load. Can be a
                        pyproject.toml in which case the code is looked up
                        under the tool.novella.script key. (default: None)
  -d DIRECTORY, --directory DIRECTORY
                        Switch to the specified directory before executing the
                        configuration file.
  -b PATH, --build-directory PATH
                        The build directory. If not specified, a temporary
                        directory will be created.
  -r, --use-reloader    Enable reloading, which will re-execute the pipeline
                        if a watched file changes.
  --dot                 Produce a DotViz representation of the build graph.
  --intercept ACTION    The name of an action to intercept and pause the
                        execution, waiting for user input to continue. Useful
                        for debugging intermediate steps of the build process.
                        Currently, the action name must be matched exactly and
                        actions can only be intercepted before they are run.
                        If this option is provided, all possible intercept
                        points are logged to the console.

template (mkdocs):
  --serve               Use mkdocs serve
  --port PORT           The port to serve under
  --site-dir PATH       Build directory for MkDocs (defaults to "_site")
  --base-url URL        The base URL to prefix to autogenerated link inside
                        the documentation.

Advantages over the YAML Configuration

The YAML Configuration allows you to define in one file all pages and the Python API objects they should contain. However, when you use Novella, each page will need to exist as a Markdown file. This has a few advantages:

  • Easier to understand; The YAML pages configuration could be hard to reason about, while having an actual file for each page is much more human friendly and actually resembles the project structure for the static site generator in use.
  • 1-to-1 mapping; Each page in the final documentation is represented by a file in the source project, allowing things like the "Edit URL" generated by MkDocs to point to the actual page source rather than a 404 page.
  • Mixing static and generated content; Placing generated API documentation where the @pydoc tag is used in the Markdown page allows you to put static documentation content around it.

Now, if you still want to generate Markdown files at build time, Pydoc-Markdown does not currently provide any functionality to do that; although some discussion around the topic is happening in #245. However, the Novella build script is just code, so if you really need it, you can generate the files there:

template "mkdocs"

def api_pages = {
  "SomeClass": "my_module.SomeClass",
  # ...

action "mkdocs-update-config" {
  site_name = "My module"
  profile = "readthedocs"
  update_with config -> {
    def items = []
    for title, package in api_pages.items():
      items.append({ title: 'api/{}.md'.format(package) })
    config['nav'].append({ 'API Documentation': items })

action "preprocess-markdown" {
  use "pydoc"

  name: "generate-api-pages"
  closure: {
    # Make sure that this action runs before the Markdown preprocessors.
    precedes "preprocess-markdown"
  action: {
    for title, package in api_pages.items():
      def path = directory / 'content' / 'api' / (package + '.md')
      path.parent.mkdir(parents=True, exist_ok=True)
      path.write_text('---\ntitle: {}\n---\n@pydoc {}\n'.format(title, package))