Giter Site home page Giter Site logo

mkdocs-typer's Introduction

mkdocs-typer

Tests Python versions Package version

An MkDocs extension to generate documentation for Typer command line applications.

Installation

Install from PyPI:

pip install mkdocs-typer

Quickstart

Add mkdocs-typer to Markdown extensions in your mkdocs.yml configuration:

site_name: Example
theme: readthedocs

markdown_extensions:
    - mkdocs-typer

Add a CLI application, e.g.:

# app/cli.py
import typer


my_app = typer.Typer()


@my_app.command()
def foo():
    """do something fooey"""


@my_app.callback()
def cli():
    """
    Main entrypoint for this dummy program
    """

Add a mkdocs-typer block in your Markdown:

# CLI Reference

This page provides documentation for our command line tools.

::: mkdocs-typer
    :module: app.cli
    :command: cli

Start the docs server:

mkdocs serve

Tada! ๐Ÿ’ซ

Usage

Documenting commands

To add documentation for a command, add a mkdocs-typer block where the documentation should be inserted.

Example:

::: mkdocs-typer
    :module: app.cli
    :command: main

For all available options, see the Block syntax.

Multi-command support

When pointed at a group (or any other multi-command), mkdocs-typer will also generate documentation for sub-commands.

This allows you to generate documentation for an entire CLI application by pointing mkdocs-typer at the root command.

Tweaking header levels

By default, mkdocs-typer generates Markdown headers starting at <h1> for the root command section. This is generally what you want when the documentation should fill the entire page.

If you are inserting documentation within other Markdown content, you can set the :depth: option to tweak the initial header level. Note that this applies even if you are just adding a heading.

By default it is set to 0, i.e. headers start at <h1>. If set to 1, headers will start at <h2>, and so on. Note that if you insert your own first level heading and leave depth at its default value of 0, the page will have multiple <h1> tags, which is not compatible with themes that generate page-internal menus such as the ReadTheDocs and mkdocs-material themes.

Reference

Block syntax

The syntax for mkdocs-typer blocks is the following:

::: mkdocs-typer
    :module: <MODULE>
    :command: <COMMAND>
    :prog_name: <PROG_NAME>
    :depth: <DEPTH>

Options:

  • module: path to the module where the command object is located.
  • command: name of the command object.
  • prog_name: (Optional, default: same as command) the name to display for the command.
  • depth: (Optional, default: 0) Offset to add when generating headers.

mkdocs-typer's People

Contributors

bruce-szalwinski avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar

Forkers

masasin

mkdocs-typer's Issues

ModuleNotFoundError while running package example

Issue

Hi thank you for supporting this package โค๏ธ

I can't get the package example working. I am using an old version of the package 0.0.2 (can't update for project reasons), python 3.9.18

Mkdocs-typer doesn't find the app module ...

Project file structure

tree
.
โ”œโ”€โ”€ app
โ”‚   โ”œโ”€โ”€ __init__.py
โ”‚   โ””โ”€โ”€ cli.py
โ”œโ”€โ”€ docs
โ”‚   โ”œโ”€โ”€ index.md
โ”‚   โ””โ”€โ”€ typer.md
โ””โ”€โ”€ mkdocs.yml
# app/cli.py
import typer

my_app = typer.Typer()


@my_app.command()
def foo():
    """do something fooey"""


@my_app.callback()
def cli():
    """
    Main entrypoint for this dummy program
    """
# typer.md

This page provides documentation for our command line tools.

::: mkdocs-typer
    :module: app.cli
    :command: cli

$ mkdocs serve
INFO    -  Building documentation...
INFO    -  Cleaning site directory
ERROR   -  Error reading page 'typer.md': No module named 'app'
Traceback (most recent call last):
  File "/opt/homebrew/anaconda3/envs/env-doc/bin/mkdocs", line 8, in <module>
    sys.exit(cli())
  File "/opt/homebrew/anaconda3/envs/env-doc/lib/python3.9/site-packages/click/core.py", line 1157, in __call__
    return self.main(*args, **kwargs)
  File "/opt/homebrew/anaconda3/envs/env-doc/lib/python3.9/site-packages/click/core.py", line 1078, in main
    rv = self.invoke(ctx)
  File "/opt/homebrew/anaconda3/envs/env-doc/lib/python3.9/site-packages/click/core.py", line 1688, in invoke
    return _process_result(sub_ctx.command.invoke(sub_ctx))
  File "/opt/homebrew/anaconda3/envs/env-doc/lib/python3.9/site-packages/click/core.py", line 1434, in invoke
    return ctx.invoke(self.callback, **ctx.params)
  File "/opt/homebrew/anaconda3/envs/env-doc/lib/python3.9/site-packages/click/core.py", line 783, in invoke
    return __callback(*args, **kwargs)
  File "/opt/homebrew/anaconda3/envs/env-doc/lib/python3.9/site-packages/mkdocs/__main__.py", line 270, in serve_command
    serve.serve(**kwargs)
  File "/opt/homebrew/anaconda3/envs/env-doc/lib/python3.9/site-packages/mkdocs/commands/serve.py", line 98, in serve
    builder(config)
  File "/opt/homebrew/anaconda3/envs/env-doc/lib/python3.9/site-packages/mkdocs/commands/serve.py", line 79, in builder
    build(config, live_server=None if is_clean else server, dirty=is_dirty)
  File "/opt/homebrew/anaconda3/envs/env-doc/lib/python3.9/site-packages/mkdocs/commands/build.py", line 322, in build
    _populate_page(file.page, config, files, dirty)
  File "/opt/homebrew/anaconda3/envs/env-doc/lib/python3.9/site-packages/mkdocs/commands/build.py", line 175, in _populate_page
    page.render(config, files)
  File "/opt/homebrew/anaconda3/envs/env-doc/lib/python3.9/site-packages/mkdocs/structure/pages.py", line 271, in render
    self.content = md.convert(self.markdown)
  File "/opt/homebrew/anaconda3/envs/env-doc/lib/python3.9/site-packages/markdown/core.py", line 354, in convert
    self.lines = prep.run(self.lines)
  File "/opt/homebrew/anaconda3/envs/env-doc/lib/python3.9/site-packages/mkdocs_typer/_extension.py", line 31, in run
    return list(replace_blocks(lines, title="mkdocs-typer", replace=replace_command_docs))
  File "/opt/homebrew/anaconda3/envs/env-doc/lib/python3.9/site-packages/mkdocs_typer/_processing.py", line 34, in replace_blocks
    yield from replace(**options)
  File "/opt/homebrew/anaconda3/envs/env-doc/lib/python3.9/site-packages/mkdocs_typer/_extension.py", line 24, in replace_command_docs
    command_obj = load_command(module, command)
  File "/opt/homebrew/anaconda3/envs/env-doc/lib/python3.9/site-packages/mkdocs_typer/_loader.py", line 14, in load_command
    command = _load_obj(module, attribute)
  File "/opt/homebrew/anaconda3/envs/env-doc/lib/python3.9/site-packages/mkdocs_typer/_loader.py", line 24, in _load_obj
    mod = importlib.import_module(module)
  File "/opt/homebrew/anaconda3/envs/env-doc/lib/python3.9/importlib/__init__.py", line 127, in import_module
    return _bootstrap._gcd_import(name[level:], package, level)
  File "<frozen importlib._bootstrap>", line 1030, in _gcd_import
  File "<frozen importlib._bootstrap>", line 1007, in _find_and_load
  File "<frozen importlib._bootstrap>", line 972, in _find_and_load_unlocked
  File "<frozen importlib._bootstrap>", line 228, in _call_with_frames_removed
  File "<frozen importlib._bootstrap>", line 1030, in _gcd_import
  File "<frozen importlib._bootstrap>", line 1007, in _find_and_load
  File "<frozen importlib._bootstrap>", line 984, in _find_and_load_unlocked
ModuleNotFoundError: No module named 'app'

Conda env

Package                    Version
-------------------------- ----------
certifi                    2023.11.17
charset-normalizer         3.3.2
click                      8.1.7
colorama                   0.4.6
ghp-import                 2.1.0
griffe                     0.38.1
idna                       3.6
importlib-metadata         7.0.0
Jinja2                     3.1.2
Markdown                   3.5.1
MarkupSafe                 2.1.3
mergedeep                  1.3.4
mkdocs                     1.5.1
mkdocs-autorefs            0.4.1
mkdocs-material            9.1.21
mkdocs-material-extensions 1.3.1
mkdocs-typer               0.0.2
mkdocstrings               0.24.0
mkdocstrings-python        0.8.3
packaging                  23.2
pathspec                   0.12.1
pip                        23.3.1
platformdirs               4.1.0
Pygments                   2.17.2
pymdown-extensions         10.5
python-dateutil            2.8.2
PyYAML                     6.0.1
pyyaml_env_tag             0.1
regex                      2023.10.3
requests                   2.31.0
setuptools                 68.2.2
six                        1.16.0
typer                      0.9.0
typing_extensions          4.9.0
urllib3                    2.1.0
watchdog                   3.0.0
wheel                      0.42.0
zipp                       3.17.0

Example from README not working

Hi, and thanks for this library!

I'm trying the example from the README, but I'm getting the following error:

mkdocs_typer._exceptions.MkDocsTyperException: 'cli' must be a 'typer.main.Typer' object, got <class 'function'>

If I use :command: my_app (instead of cli), I get no error, but I see a big my_app in the docs:

Screenshot 2023-11-27 at 01 52 12
  1. Is there a bug?
  2. Am I doing something wrong?
  3. Is it possible to hide that my_app header? I tried playing with :depth: with no luck.

Indented ::: mkdocs-typer blocks are not picked up

Sister of mkdocs/mkdocs-click#67


Users of mkdocstrings noticed that indented mkdocs-typer blocks are not picked up and handled by mkdocs-typer, and later (block processors) mkdocstrings picks it up (we use the same syntax :::) and errors out since it do not support the rest of the syntax.

Would it be possible to loosen a bit the regex to match blocks starting with spaces?

The alternative is to implement the processor as a block processor rather than a pre-processor, and indentation will be handled for you automatically. You'd just have to make sure to keep using a higher priority than mkdocstrings, since you match the contents after ::: more specifically (strictly equal to mkdocs-typer in your case, while mkdocstrings matches anything).

For reference, our block processor implementation:

Unable to resolve `help` string literal when using `Annotated[]`

Defining a Typer endpoint using Annotated[] as is the new preferred method of annotating the types:

@app.command(name="open_files")
def main(
    files: Annotated[
        list[Path],
        Argument(
            help="Input files",
        ),
    ],
) -> None:

Results in an error:

$ mkdocs serve
INFO     -  Building documentation...
INFO     -  Cleaning site directory
ERROR    -  griffe: main.py:24: Failed to get annotation expression from Subscript: invalid syntax (<string-annotation>, line 1)

Environment

  • Python 3.10.11
mkdocs                         1.3.0
mkdocs-autorefs                0.4.1
mkdocs-include-markdown-plugin 4.0.4
mkdocs-material                8.5.4
mkdocs-material-extensions     1.1.1
mkdocs-typer                   0.0.2
mkdocstrings                   0.22.0
mkdocstrings-python            1.1.2

project status

hi @bruce-szalwinski ,
Project seems great to me, and I was planning to use it, but the repo seems abandoned.
Is it actively used or you would recommend iskng mkdocs-click on top of click object that can be taken from Typer?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.