from quartodoc import collect, preview
from quartodoc import MdRenderer
import yaml
Components: Auto, blueprint, collect
Auto
: Config Options
The Auto
class contains data about how you wish to render a specific Python object, which you typically set in configuration options via the quartodoc
section of your _quarto.yml
file. In other words, Auto
is a data structure that represents the configuration options for a specific Python object.
In the previous section, be demonstrated how we can find the Auto
object corresponding to the MdRenderer
class from our yaml configuration:
We can find the Auto
object corresponding to the python object from our yaml configuration like this:
import yaml
from quartodoc import Builder
= yaml.safe_load("""
cfg quartodoc:
package: quartodoc
style: pkgdown
sections:
- title: "Some section"
desc: "Some description"
contents:
- name: MdRenderer
members: ["render", "summarize"]
children: separate
""")
= Builder.from_quarto_config(cfg)
builder = builder.layout.sections[0].contents[0]
auto_from_yml print(auto_from_yml)
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'
We can see many of the configuration options such as members
, name
and children
as well as other options we didn’t specify but are set to their default values. For example, we didn’t set the option for dynamic
but it is set to false
by default.
However, we don’t have to start with yaml
files to create an Auto
object. We can also create an Auto
object with the fully qualified name of any Python object. For example, we can create an Auto
object for the MdRenderer
class like this:
from quartodoc import Auto
= Auto(name = "quartodoc.MdRenderer",
auto = 'short')
signature_name print(auto)
signature_name='short' members=None 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.embedded: 'embedded'> package=MISSING() member_order='alphabetical' member_options=None kind='auto' name='quartodoc.MdRenderer'
However, since we didn’t specify any options, this is not the same Auto
that we got from the yaml. For example, the members
option is not set to ["render", "summarize"]
as it was in the yaml. Instead, it is set to None
which means that all members will be included. We can see this by looking at the obj
attribute of the Auto
object:
print(auto.members)
None
To set this option, we can pass it to the Auto
constructor:
= Auto(name = "quartodoc.MdRenderer",
auto = ["render", "summarize"]
members
)
assert auto.members == auto_from_yml.members
print(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.embedded: 'embedded'> package=MISSING() member_order='alphabetical' member_options=None kind='auto' name='quartodoc.MdRenderer'
Understanding the Auto
object is helpful for debugging quartodoc
. If you find that a configuration option is not being set as you expect, you can create an Auto
object for the Python object in question and compare it to the Auto
object that you expect to be created from your yaml configuration.
blueprint
: Parse Metadata From Objects
blueprint
parses all of the metadata about the python object and stores it in a hierarchal tree structure that is convenient for a renderer to transform into a renderable format like HTML or Markdown. For example, here is the blueprint for the MdRenderer
class:
from quartodoc import blueprint
= blueprint(auto)
doc =2) preview(doc, max_depth
█─DocClass
├─name = 'quartodoc.MdRenderer'
├─obj = █─Alias
│ ├─name = 'MdRenderer'
│ ├─canonical_path = 'quartodoc.renderers.md_renderer.MdRenderer'
│ ├─classes = █─dict ...
│ ├─parameters = █─Parameters ...
│ ├─members = █─dict ...
│ ├─functions = █─dict ...
│ └─docstring = █─Docstring ...
├─anchor = 'quartodoc.MdRenderer'
├─members = █─list
│ ├─0 = █─DocFunction ...
│ └─1 = █─DocFunction ...
└─flat = False
To give you a sense of this tree structure, we can look at the obj.docstring
field of the above blueprint, which contains information about the Python docstring:
=2) preview(doc.obj.docstring, max_depth
█─Docstring
├─parser = <Parser.numpy: 'numpy'>
└─parsed = █─list
├─0 = █─DocstringSectionText ...
├─1 = █─DocstringSectionParameters ...
└─2 = █─DocstringSectionExamples ...
We can see from this output that the parser for the docstring is numpy
, which means the docstring is expected to be in the numpy style.
Furthermore, we can see from the tree structure that the DocstringSectionText
is stored as the first element in a list under the parsed
attribute:
0]) preview(doc.obj.docstring.parsed[
█─DocstringSectionText
├─kind = <DocstringSectionKind.text: 'text'>
├─title = None
└─value = 'Render docstrings to markdown.'
DocstringSectionText
stores the “text” field of a numpy style docstring, which is the first line of the docstring, which is otherwise known as the short summary. Furthermore, we can see from the output above that the actual text of this short summary is stored in the value
attribute:
= doc.obj.docstring.parsed[0].value
docstr_firstln_value print(docstr_firstln_value)
Render docstrings to markdown.
We can check the docstring of MdRenderer
to see that this is indeed the first line of the docstring:
from inspect import getdoc
= getdoc(MdRenderer).splitlines()[0]
docstr_firstln
# These are the same
assert docstr_firstln == docstr_firstln_value
print(docstr_firstln)
Render docstrings to markdown.
Layout & Sections
The Layout
class stores how you wish to organize your documentation. For example, you may wish to organize your documentation into sections, where each section contains a title, description, and a list of objects to document. You can create a layout like this:
import yaml
from quartodoc import Builder
= yaml.safe_load("""
cfg quartodoc:
package: quartodoc
sections:
- title: "Some section"
desc: "Some description"
contents:
- name: MdRenderer
- title: "Another section"
desc: "Another description"
contents:
- Auto
- blueprint
""")
= Builder.from_quarto_config(cfg)
builder = builder.layout.sections[0].contents[0]
auto_from_yml =3) preview(builder.layout, max_depth
█─Layout
├─sections = █─list
│ ├─0 = █─Section
│ │ ├─title = 'Some section'
│ │ ├─desc = 'Some description'
│ │ └─contents = █─list ...
│ └─1 = █─Section
│ ├─title = 'Another section'
│ ├─desc = 'Another description'
│ └─contents = █─list ...
└─package = 'quartodoc'
As you can see, the Layout
stores the sections, which are stored in the sections
attribute. Each section contains a title
, desc
, and contents
attribute and is stored in a Section
class.
The contents
attribute is a list of objects to document. In this case, the first section contains a single object, the MdRenderer
class, while the second section contains two objects. You can read more about Section options here.
In addition to building a layout from a yaml file, you can also build a layout in Python by instantiating the Layout
class like so:
from quartodoc import Auto, layout
= Auto(name = "quartodoc.MdRenderer",
auto = 'short')
signature_name
= layout.Layout(
lay = [
sections = "A section",
layout.Section(title = "A description",
desc = [auto])
contents
] )
We can view the layout by calling the preview
function:
preview(lay, =8,
max_depth=True) compact
█─Layout
└─sections =
█─list
└─0 =
█─Section
├─title = 'A section'
├─desc = 'A description'
└─contents =
█─list
└─0 =
█─Auto
├─signature_name = 'short'
└─name = 'quartodoc.MdRenderer'
Recall that the blueprint
function parses all of the metadata about the Python object. We can see how a blueprint adds additional data pertaining to MdRenderer
, that wasn’t present in the layout above:
= blueprint(lay)
bp_layout
preview(bp_layout, =8,
max_depth=True) compact
█─Layout
└─sections =
█─list
└─0 =
█─Section
├─title = 'A section'
├─desc = 'A description'
└─contents =
█─list
└─0 =
█─Page
├─path = 'quartodoc.MdRenderer'
└─contents =
█─list
└─0 =
█─DocClass
├─name = 'quartodoc.MdRenderer'
├─obj =
│ █─Alias
│ ├─name = 'MdRenderer'
│ ├─canonical_path = 'quartodoc.renderers.md_renderer.MdRenderer'
│ ├─classes = █─dict ...
│ ├─parameters =
│ │ █─Parameters ...
│ ├─members =
│ │ █─dict ...
│ ├─functions =
│ │ █─dict ...
│ └─docstring =
│ █─Docstring ...
├─anchor = 'quartodoc.MdRenderer'
├─signature_name = 'short'
├─members =
│ █─list
│ └─0 =
│ █─DocFunction ...
└─flat = False
Grouping docs on a page
The Layout also calculates how to split your sections into pages based on the options you set in your yaml configuration. For example, if you set the children
option to separate
, then each object in a section will be placed on its own page.
Let’s see the difference between the separate
and embedded
options by creating two Auto
objects for the MdRenderer
class, one with children
set to separate
and the other with children
set to embedded
:
= layout.Auto(name = "quartodoc.MdRenderer",
auto_sep = "separate")
children = layout.Auto(name = "quartodoc.MdRenderer",
auto_emb = "embedded") children
= blueprint(auto_emb)
bp_emb
preview(bp_emb, =2,
max_depth=True) compact
█─DocClass
├─name = 'quartodoc.MdRenderer'
├─obj =
│ █─Alias
│ ├─name = 'MdRenderer'
│ ├─canonical_path = 'quartodoc.renderers.md_renderer.MdRenderer'
│ ├─classes = █─dict ...
│ ├─parameters =
│ │ █─Parameters ...
│ ├─members =
│ │ █─dict ...
│ ├─functions =
│ │ █─dict ...
│ └─docstring =
│ █─Docstring ...
├─anchor = 'quartodoc.MdRenderer'
├─members =
│ █─list
│ └─0 =
│ █─DocFunction ...
└─flat = False
= blueprint(auto_sep)
bp_sep
preview(bp_sep, =2,
max_depth=True) compact
█─DocClass
├─name = 'quartodoc.MdRenderer'
├─obj =
│ █─Alias
│ ├─name = 'MdRenderer'
│ ├─canonical_path = 'quartodoc.renderers.md_renderer.MdRenderer'
│ ├─classes = █─dict ...
│ ├─parameters =
│ │ █─Parameters ...
│ ├─members =
│ │ █─dict ...
│ ├─functions =
│ │ █─dict ...
│ └─docstring =
│ █─Docstring ...
├─anchor = 'quartodoc.MdRenderer'
├─members =
│ █─list
│ └─0 =
│ █─MemberPage ...
└─flat = False
Collect: fetch all pages and items
= layout.Page(path = "some_doc_page", contents = [doc])
some_page = collect(some_page, "reference")
pages, items pages
[Page(kind='page', path='some_doc_page', package=MISSING(), summary=None, flatten=False, contents=[DocClass(name='quartodoc.MdRenderer', obj=Alias('MdRenderer', 'quartodoc.renderers.MdRenderer'), anchor='quartodoc.MdRenderer', signature_name='relative', kind='class', members=[DocFunction(name='render', obj=Alias('render', 'quartodoc.renderers.md_renderer.MdRenderer.render'), anchor='quartodoc.MdRenderer.render', signature_name='relative', kind='function'), DocFunction(name='summarize', obj=Alias('summarize', 'quartodoc.renderers.md_renderer.MdRenderer.summarize'), anchor='quartodoc.MdRenderer.summarize', signature_name='relative', kind='function')], flat=False)])]