While the “Basic Use” section covered how to configure and build a site with quartodoc, this section focuses on using quartodoc as a Python program.
Programming with quartodoc will help with debugging, tinkering, and extending things.
Overview
When a user runs quartodoc build
, they
Create a Builder object, with the quartodoc config loaded as a layout.Layout .
Use blueprint to process the layout into a plan for building the website.
Use collect to get pages to render, and info on where documented objects live.
This page will cover the basics of the Builder and this process.
The Builder
The code below shows a Builder object being loaded from a _quarto.yml
config (loaded as a Python dictionary).
import yaml
from quartodoc import Builder, blueprint, collect, MdRenderer
cfg = yaml.safe_load("""
quartodoc:
package: quartodoc
style: pkgdown
sections:
- title: "Some section"
desc: "Some description"
contents:
- name: MdRenderer
members: ["render", "summarize"]
children: separate
""" )
builder = Builder.from_quarto_config(cfg)
builder
<quartodoc.autosummary.BuilderPkgdown at 0x7f1a94d2a260>
Note that .from_quarto_config used the style:
field to decide which Builder to create (in this case, BuilderPkgdown
).
We can view the config as a layout.Layout , by looking at the .layout
attribute.
Layout(sections=[Section(kind='section', title='Some section', subtitle=None, desc='Some description', package=MISSING(), contents=[Auto(signature_name='relative', members=['render', 'summarize'], include_private=False, include_imports=False, include_empty=False, include_inherited=False, include_attributes=True, include_classes=True, include_functions=True, include=None, exclude=None, dynamic=None, children=<ChoicesChildren.separate: 'separate'>, package=MISSING(), member_order='alphabetical', member_options=None, kind='auto', name='MdRenderer')], options=None)], package='quartodoc', options=None)
This can be a bit difficult to read, so quartodoc implements a preview function, which spaces things out.
from quartodoc import preview
preview(builder.layout)
█─Layout
├─sections = █─list
│ └─0 = █─Section
│ ├─title = 'Some section'
│ ├─desc = 'Some description'
│ └─contents = █─list
│ └─0 = █─Auto
│ ├─members = █─list
│ │ ├─0 = 'render'
│ │ └─1 = 'summarize'
│ ├─children = <ChoicesChildren.separate: 'separate'>
│ └─name = 'MdRenderer'
└─package = 'quartodoc'
Notice the following:
preview
represents calls like Layout()
with a box to the left, and then a pipe connecting it to each of its arguments.
The content entry MdRenderer
is represented by an Auto class. This specifies a Python object to look up and document.
We can follow the path in the preview above, to pull out just this first piece of content containing MdRenderer
:
content = builder.layout.sections[0 ].contents[0 ]
preview(content)
█─Auto
├─members = █─list
│ ├─0 = 'render'
│ └─1 = 'summarize'
├─children = <ChoicesChildren.separate: 'separate'>
└─name = 'MdRenderer'
Next, we’ll look at blueprint()
, which processes the layout, including transforming Auto
objects (like the one representing the MdRenderer
above) into more concrete instructions.
From config to blueprint
The code below shows how blueprint()
transforms the Auto
entry for MdRenderer
.
bp = blueprint(builder.layout)
bp_contents = bp.sections[0 ].contents[0 ]
preview(bp_contents, max_depth= 3 )
█─Page
├─path = 'MdRenderer'
└─contents = █─list
└─0 = █─DocClass
├─name = 'MdRenderer'
├─obj = █─Alias ...
├─anchor = 'quartodoc.MdRenderer'
├─members = █─list ...
└─flat = False
Notice two key pieces:
The Auto
element is now a layout.Page . The .path
indicates that the documentation will be on a page called "MdRenderer"
.
The content of the page is a layout.DocClass
. This element holds everything needed to render this doc, including the class signature and parsed docstring.
Importantly, the .members
attribute stores how to render the class methods we listed in our configuration yaml, .render()
and .summarize()
:
preview(bp_contents.contents[0 ].members, max_depth= 2 )
█─list
├─0 = █─MemberPage
│ ├─path = 'quartodoc.MdRenderer.render'
│ └─contents = █─list ...
└─1 = █─MemberPage
├─path = 'quartodoc.MdRenderer.summarize'
└─contents = █─list ...
Note that they are also a instances of Page
(MemberPage
to be exact). Before to building the site, we need to collect()
all the pages.
Collecting pages and items
The collect function pulls out two important pieces of information:
pages - each page to be rendered.
items - information on where each documented object lives in the site, which is used for things like interlinks .
pages, items = collect(bp, builder.dir )
preview(pages, max_depth= 3 )
█─list
├─0 = █─MemberPage
│ ├─path = 'quartodoc.MdRenderer.render'
│ └─contents = █─list
│ └─0 = █─DocFunction ...
├─1 = █─MemberPage
│ ├─path = 'quartodoc.MdRenderer.summarize'
│ └─contents = █─list
│ └─0 = █─DocFunction ...
└─2 = █─Page
├─path = 'MdRenderer'
└─contents = █─list
└─0 = █─DocClass ...
The code below shows a preview of the items.
preview(items, max_depth= 2 )
█─list
├─0 = █─Item
│ ├─name = 'quartodoc.MdRenderer.render'
│ ├─obj = █─Alias ...
│ └─uri = 'reference/quartodoc.MdRenderer.render.html#quarto ...
├─1 = █─Item
│ ├─name = 'quartodoc.renderers.md_renderer.MdRenderer.render ...
│ ├─obj = █─Alias ...
│ ├─uri = 'reference/quartodoc.MdRenderer.render.html#quarto ...
│ └─dispname = 'quartodoc.MdRenderer.render'
├─2 = █─Item
│ ├─name = 'quartodoc.MdRenderer.summarize'
│ ├─obj = █─Alias ...
│ └─uri = 'reference/quartodoc.MdRenderer.summarize.html#qua ...
├─3 = █─Item
│ ├─name = 'quartodoc.renderers.md_renderer.MdRenderer.summar ...
│ ├─obj = █─Alias ...
│ ├─uri = 'reference/quartodoc.MdRenderer.summarize.html#qua ...
│ └─dispname = 'quartodoc.MdRenderer.summarize'
├─4 = █─Item
│ ├─name = 'quartodoc.MdRenderer'
│ ├─obj = █─Alias ...
│ └─uri = 'reference/MdRenderer.html#quartodoc.MdRenderer'
└─5 = █─Item
├─name = 'quartodoc.renderers.md_renderer.MdRenderer'
├─obj = █─Alias ...
├─uri = 'reference/MdRenderer.html#quartodoc.MdRenderer'
└─dispname = 'quartodoc.MdRenderer'
Notice that if you wanted to look up quartodoc.MdRenderer.render
, the first item’s .uri
attribute shows the URL for it, relative to wherever the doc site is hosted.
Rendering and writing
A Builder
instantiates a Renderer
(like MdRenderer
). Use the .renderer
attribute to access it:
<quartodoc.renderers.md_renderer.MdRenderer at 0x7f1a94d1e4a0>
The render
method of of the MdRenderer
returns a markdown string that can be rendered by Quarto:
print (builder.renderer.render(pages[0 ]))
# render { #quartodoc.MdRenderer.render }
```python
MdRenderer.render(el)
```
The { #quartodoc.MdRenderer.render }
in the output above is extended Quarto markdown that is a cross reference .
Writing pages
The builder has a number of methods it uses while materializing files that will be rendered by Quarto. The main method is .build() . See the Builder section of the API for a list of methods, or this giant build process diagram for a full breakdown.