smalldocs.api
smalldocs api build one page per module into the site, and the index of names for links smalldocs api check what is typed and documented, and every gap; exit 1 if any smalldocs api module NAME one module as plain Markdown smalldocs api list every module, class, method and function, one line each
Types come from the annotations, the description of a parameter from its docment (the comment beside
it, read by fastcore), and the summary from the docstring. A dataclass shows its constructor, a pydantic
model its fields with their descriptions or the comment beside each, a TypedDict its keys with the comment
beside each, and a click command its function and its options. The settings are api in _smalldocs.yml,
or smalldocs.api in _quarto.yml:
api:
packages: [mypkg] # importable packages to document
out: api # the folder of pages, inside the site
root: .. # the repository's root, from the site's folder
source: https://github.com/me/mypkg/blob/main # where `source` links point
check: ["*.py", "docs/*.py", "tests/**/*.py"] # more files that `check` holds to the convention, from the rootclass Symbol
Symbol(module: str, name: str, kind: str, summary: str, line: int)One line of the inventory: a module, a class, a method or a function, and where it is.
| Parameter | Type | Default | Description |
|---|---|---|---|
module |
str | required | The module’s full name, such as mypkg.api |
name |
str | required | render or Choice._check: the name inside the module; empty for the module |
kind |
str | required | module, class, method or function |
summary |
str | required | The first line of the docstring, or empty when there is none |
line |
int | required | The line the definition starts on; 1 for a module |
package_modules
package_modules(package: str) -> list[ModuleType]Import every public module of a package, its subpackages’ too, in name order; the package itself when it defines code.
| Parameter | Type | Default | Description |
|---|---|---|---|
package |
str | required | The name of an importable package, or of a single module |
| returns | list[ModuleType] | The package, when its __init__ defines code, then its public modules and its subpackages’, in name order |
file_modules
file_modules(files: list[Path], root: Path | None = None) -> list[ModuleType]Import Python files as modules of their own, named by their paths from the root, such as tests/test_x.py.
| Parameter | Type | Default | Description |
|---|---|---|---|
files |
list[Path] | required | Python files that are not part of a package |
root |
Path | None | None |
The folder that names start from; None names each file by its full path |
| returns | list[ModuleType] | One module per file, named by its path, in the order given |
module
module(name: str, packages: list[str]) -> ModuleTypeFind one module by its short name or its full name.
| Parameter | Type | Default | Description |
|---|---|---|---|
name |
str | required | The module’s short name, api, or its full name, mypkg.api |
packages |
list[str] | required | The packages to look in |
| returns | ModuleType | The imported module; LookupError when there is no such module |
doc
doc(obj: object) -> strRead an object’s own docstring, cleaned of its indentation; empty when there is none.
| Parameter | Type | Default | Description |
|---|---|---|---|
obj |
object | required | A module, class or function |
| returns | str | Its own docstring, cleaned of its indentation; empty when there is none |
summary
summary(obj: object) -> strRead the first line of an object’s docstring.
| Parameter | Type | Default | Description |
|---|---|---|---|
obj |
object | required | A module, class or function |
| returns | str | The first line of its docstring; empty when there is none |
line_of
line_of(sym: Code) -> intFind the line a symbol’s definition starts on, to keep symbols in source order.
| Parameter | Type | Default | Description |
|---|---|---|---|
sym |
Code | required | A function, method or class |
| returns | int | The line its definition starts on |
unwrapped
unwrapped(obj: object) -> objectSee through a decorator that kept the function, as functools.wraps, a fixture and a click command do.
| Parameter | Type | Default | Description |
|---|---|---|---|
obj |
object | required | Anything a module or a class holds under a name |
| returns | object | The function inside it when it is a decorator’s wrapper or a click command; otherwise the object itself |
is_command
is_command(obj: object) -> boolTell whether an object is a click command: it has a function in callback, a list in params and a name.
| Parameter | Type | Default | Description |
|---|---|---|---|
obj |
object | required | Anything a module holds under a name |
| returns | bool | Whether it is a click command or group, found by its shape, without importing click |
command_of
command_of(func: FunctionType, mod: ModuleType) -> object | NoneFind the click command that a function is the callback of, to list its options.
| Parameter | Type | Default | Description |
|---|---|---|---|
func |
FunctionType | required | A function |
mod |
ModuleType | required | The module it was written in |
| returns | object | None | The click command or group in the module whose function it is; None when there is none |
own
own(mod: ModuleType, private: bool = False) -> list[Code]List the functions and classes a module defines itself, in source order; not its imports.
| Parameter | Type | Default | Description |
|---|---|---|---|
mod |
ModuleType | required | An imported module |
private |
bool | False |
Include names that start with an underscore |
| returns | list[Code] | The functions and classes the module defines, in source order |
is_dunder
is_dunder(name: str) -> boolTell whether a name is one of Python’s own, such as __init__: a dataclass writes those.
| Parameter | Type | Default | Description |
|---|---|---|---|
name |
str | required | An attribute name |
| returns | bool | Whether it is one of Python’s own, written __like_this__ |
methods
methods(klass: type, private: bool = False) -> list[FunctionType]List the methods a class defines itself, in source order, not what it inherits.
| Parameter | Type | Default | Description |
|---|---|---|---|
klass |
type | required | A class |
private |
bool | False |
Include names that start with one underscore |
| returns | list[FunctionType] | The methods the class defines, in source order |
held
held(mod: ModuleType) -> list[Code]List everything check holds to the convention: every function, class and method.
| Parameter | Type | Default | Description |
|---|---|---|---|
mod |
ModuleType | required | An imported module |
| returns | list[Code] | Every function, class and method in it, private ones too |
inventory
inventory(packages: list[str]) -> list[Symbol]List every public module, class, method and function of the packages, with its summary.
| Parameter | Type | Default | Description |
|---|---|---|---|
packages |
list[str] | required | The names of importable packages |
| returns | list[Symbol] | One entry per public module, class, method and function, in source order |
name_of
name_of(anno: object, mod: ModuleType) -> str | NoneFind what a module calls a type: an alias such as JSONContent, or the name it imported.
| Parameter | Type | Default | Description |
|---|---|---|---|
anno |
object | required | A type, as an annotation holds it |
mod |
ModuleType | required | The module the annotation was written in |
| returns | str | None | The name that module gives the type, or None when it has none |
type_text
type_text(anno: object, mod: ModuleType) -> strWrite a type the way the source does: JSONContent, not the union it stands for.
| Parameter | Type | Default | Description |
|---|---|---|---|
anno |
object | required | A type, as an annotation holds it |
mod |
ModuleType | required | The module the annotation was written in |
| returns | str | The type as the source would write it |
signature
signature(sym: Code, mod: ModuleType) -> strWrite a signature as one line of Python: each parameter with its type and default.
| Parameter | Type | Default | Description |
|---|---|---|---|
sym |
Code | required | A function, method or class |
mod |
ModuleType | required | The module it was written in |
| returns | str | Its parameters and return as one line of Python, without the name |
cell
cell(text: str) -> strMake text safe inside a Markdown table cell.
| Parameter | Type | Default | Description |
|---|---|---|---|
text |
str | required | The text of one cell |
| returns | str | The same text with every | escaped |
table
table(rows: list[list[str]], head: list[str]) -> strWrite a Markdown table, or nothing when there are no rows.
| Parameter | Type | Default | Description |
|---|---|---|---|
rows |
list[list[str]] | required | The cells of each row |
head |
list[str] | required | The column titles |
| returns | str | A Markdown table; empty when there are no rows |
safe_docments
safe_docments(sym: Code) -> dictRead the docments, or, for code with no source (made by exec, or compiled), the signature alone.
| Parameter | Type | Default | Description |
|---|---|---|---|
sym |
Code | required | A function, method or class |
| returns | dict | Each parameter’s annotation, default and docment, under its name, and return |
params_table
params_table(sym: Code, mod: ModuleType) -> strDescribe a function by its parameters and its return: type, default, docment.
| Parameter | Type | Default | Description |
|---|---|---|---|
sym |
Code | required | A function, method or dataclass |
mod |
ModuleType | required | The module it was written in |
| returns | str | A Markdown table of its parameters and its return: type, default, description |
is_model
is_model(klass: type) -> boolTell whether a class is a pydantic model: it has a dict of model_fields whose values say if they are required.
| Parameter | Type | Default | Description |
|---|---|---|---|
klass |
type | required | A class |
| returns | bool | Whether it is a pydantic model, found by its shape, without importing pydantic |
fields_table
fields_table(model: type, mod: ModuleType) -> strDescribe a pydantic model by its fields, because its constructor signature says nothing.
| Parameter | Type | Default | Description |
|---|---|---|---|
model |
type | required | A pydantic model class |
mod |
ModuleType | required | The module it was written in |
| returns | str | A Markdown table of its fields: type, default, description |
field_descriptions
field_descriptions(model: type) -> dict[str, str]Describe each field of a model: its description when it has one, or else the comment beside it.
| Parameter | Type | Default | Description |
|---|---|---|---|
model |
type | required | A pydantic model class |
| returns | dict[str, str] | For each field that has one, its description |
class_comments
class_comments(klass: type) -> dict[str, str]Read the comment beside each annotated name in one class body, such as title: str # The title.
| Parameter | Type | Default | Description |
|---|---|---|---|
klass |
type | required | A class |
| returns | dict[str, str] | For each name annotated in the class body, the comment beside it |
key_comments
key_comments(klass: type) -> dict[str, str]Read the docments of a TypedDict’s keys or a model’s fields: the comment beside each, a subclass’s first.
| Parameter | Type | Default | Description |
|---|---|---|---|
klass |
type | required | A TypedDict or a model class |
| returns | dict[str, str] | For each key that has one, the comment beside it, from the class and the classes it inherits |
parents
parents(klass: type) -> list[type]List a class and its parents; a TypedDict’s parents are in __orig_bases__, because its __mro__ is that of a dict.
| Parameter | Type | Default | Description |
|---|---|---|---|
klass |
type | required | A class |
| returns | list[type] | The class, then the classes it inherits, nearest first |
options_table
options_table(command: object) -> strDescribe a click command’s options and arguments, as its --help does.
| Parameter | Type | Default | Description |
|---|---|---|---|
command |
object | required | A click command or group |
| returns | str | A Markdown table of its options and arguments: names, default, help |
keys_table
keys_table(klass: type, mod: ModuleType) -> strDescribe a TypedDict by its keys, because calling it says nothing.
| Parameter | Type | Default | Description |
|---|---|---|---|
klass |
type | required | A TypedDict class |
mod |
ModuleType | required | The module it was written in |
| returns | str | A Markdown table of its keys: type, description |
has_init
has_init(klass: type) -> boolTell whether a class has a constructor of its own to show, as a dataclass does.
| Parameter | Type | Default | Description |
|---|---|---|---|
klass |
type | required | A class |
| returns | bool | Whether it has a constructor of its own, written by hand or by dataclass |
entry
entry(sym: Code, level: int) -> strWrite one symbol: a heading, its signature, its docstring and the table of its parameters.
| Parameter | Type | Default | Description |
|---|---|---|---|
sym |
Code | required | A function, method or class |
level |
int | required | The heading level of its entry: 2 for a top-level symbol, 3 for a method |
| returns | str | The Markdown of one entry |
module_markdown
module_markdown(mod: ModuleType) -> strWrite one module as plain Markdown: its docstring, then an entry for each public symbol.
| Parameter | Type | Default | Description |
|---|---|---|---|
mod |
ModuleType | required | An imported module |
| returns | str | The whole module as plain Markdown |
markdown
markdown(name: str, packages: list[str]) -> strWrite one module, found by name, as plain Markdown.
| Parameter | Type | Default | Description |
|---|---|---|---|
name |
str | required | The module’s short name, api, or its full name, mypkg.api |
packages |
list[str] | required | The packages to look in |
| returns | str | The whole module as plain Markdown |
gaps_of
gaps_of(sym: Code) -> list[str]Find what one symbol is missing: a docstring, a type, a docment, or a field description.
| Parameter | Type | Default | Description |
|---|---|---|---|
sym |
Code | required | A function, method or class |
| returns | list[str] | One message per gap; empty when the symbol is fully typed and documented |
gaps
gaps(mod: ModuleType) -> dict[str, list[str]]Find every gap in a module, under the module’s name and then under each symbol’s.
| Parameter | Type | Default | Description |
|---|---|---|---|
mod |
ModuleType | required | An imported module |
| returns | dict[str, list[str]] | The gaps of each symbol under its name, the module’s under its own |
check
check(packages: list[str], files: list[Path], root: Path | None = None) -> intPrint how much of each module is typed and documented, then every gap, then the total.
| Parameter | Type | Default | Description |
|---|---|---|---|
packages |
list[str] | required | The packages to hold to the convention |
files |
list[Path] | required | More Python files to hold to it, such as the tests |
root |
Path | None | None |
The folder that the names of the files start from |
| returns | int | The exit code: 0 when nothing is missing, 1 otherwise |
class Settings
Settings(site: Path, packages: list[str], out: str = 'api', root: Path | None = None, source: str = '', check: tuple[str, ...] = (), linkify: bool = True)What the api settings say: api in _smalldocs.yml, or smalldocs.api in _quarto.yml.
| Parameter | Type | Default | Description |
|---|---|---|---|
site |
Path | required | The site’s folder, which holds the config |
packages |
list[str] | required | The packages to document |
out |
str | 'api' |
The folder of pages, inside the site |
root |
Path | None | None |
The repository’s root, for source links and the files of check |
source |
str | '' |
The URL that a file’s path is added to for its source link |
check |
tuple[str, …] | () |
Globs, from the root, of more files that check holds to the convention; **/ is any folders or none |
linkify |
bool | True |
Whether a name in backticks links to its entry |
Settings.read
Settings.read(site: Path, conf: dict) -> SettingsRead the settings from the config.
| Parameter | Type | Default | Description |
|---|---|---|---|
site |
Path | required | The site’s folder |
conf |
dict | required | The smalldocs.api section |
| returns | Settings | The settings, with defaults |
Settings.importable
Settings.importable() -> NoneLet the packages import from the repository: its root and its src folder go on sys.path.
Settings.package_files
Settings.package_files() -> set[Path]Find where the documented packages are, so that check does not import their files a second time.
| Parameter | Type | Default | Description |
|---|---|---|---|
| returns | set[Path] | The folders of the documented packages, and the files of single modules |
Settings.check_files
Settings.check_files() -> list[Path]Find the files of check.
| Parameter | Type | Default | Description |
|---|---|---|---|
| returns | list[Path] | The files the globs of check find |
source_link
source_link(s: Settings, sym: Symbol) -> strLink a symbol to the line that defines it.
| Parameter | Type | Default | Description |
|---|---|---|---|
s |
Settings | required | The settings |
sym |
Symbol | required | One entry of the inventory |
| returns | str | A Markdown link to the line that defines it, or empty when there is no source |
page
page(s: Settings, mod: ModuleType, syms: list[Symbol]) -> strTurn one module’s Markdown into a page: front matter, an id and a source link for each heading.
| Parameter | Type | Default | Description |
|---|---|---|---|
s |
Settings | required | The settings |
mod |
ModuleType | required | One module |
syms |
list[Symbol] | required | The inventory entries of that module, the module’s own first |
| returns | str | The text of its .qmd page |
build
build(s: Settings) -> list[Path]Write one reference page per module, and _symbols.json, the index of names that links use.
| Parameter | Type | Default | Description |
|---|---|---|---|
s |
Settings | required | The settings |
| returns | list[Path] | The pages written |
build_from_config
build_from_config(project: object) -> list[Path]Build the reference pages that smalldocs.api asks for, before the site is rendered.
| Parameter | Type | Default | Description |
|---|---|---|---|
project |
object | required | A loaded config.Project |
| returns | list[Path] | The pages written |
main
main(site: str, action: str, name: str | None = None) -> intRun one smalldocs api command.
| Parameter | Type | Default | Description |
|---|---|---|---|
site |
str | required | The site’s folder, whose config has the api settings |
action |
str | required | build, check, module or list |
name |
str | None | None |
The module, for module |
| returns | int | The exit code |
run
run(s: Settings, action: str, name: str | None) -> intRun one smalldocs api command with its settings read.
| Parameter | Type | Default | Description |
|---|---|---|---|
s |
Settings | required | The settings |
action |
str | required | build, check, module or list |
name |
str | None | required | The module, for module |
| returns | int | The exit code |