:blue_book: Automatic documentation from sources, for MkDocs.

Overview

mkdocstrings

ci documentation pypi version conda version gitter

Automatic documentation from sources, for MkDocs.


Features - Python handler - Requirements - Installation - Quick usage

mkdocstrings_gif1

Features

  • Language-agnostic: just like MkDocs, mkdocstrings is written in Python but is language-agnostic. It means you can use it with any programming language, as long as there is a handler for it. The Python handler is built-in. Others are external. Maybe you'd like to add another one to the list? 😉

  • Multiple themes support: each handler can offer multiple themes. Currently, we offer the ⭐ Material theme ⭐ as well as basic support for the ReadTheDocs theme for the Python handler.

  • Cross-links across pages: mkdocstrings makes it possible to reference headings in other Markdown files with the classic Markdown linking syntax: [identifier][] or [title][identifier] -- and you don't need to remember which exact page this object was on. This works for any heading that's produced by a mkdocstrings language handler, and you can opt to include any Markdown heading into the global referencing scheme.

    Note: in versions prior to 0.15 all Markdown headers were included, but now you need to opt in.

  • Inline injection in Markdown: instead of generating Markdown files, mkdocstrings allows you to inject documentation anywhere in your Markdown contents. The syntax is simple: ::: identifier followed by a 4-spaces indented YAML block. The identifier and YAML configuration will be passed to the appropriate handler to collect and render documentation.

  • Global and local configuration: each handler can be configured globally in mkdocs.yml, and locally for each "autodoc" instruction.

  • Watch source code directories: you can tell mkdocstrings to add directories to be watched by MkDocs when serving the documentation, for auto-reload.

  • Reasonable defaults: you should be able to just drop the plugin in your configuration and enjoy your auto-generated docs.

Python handler

mkdocstrings_gif2

  • Data collection from source code: collection of the object-tree and the docstrings is done by pytkdocs.

  • Support for type annotations: pytkdocs collects your type annotations and mkdocstrings uses them to display parameters types or return types.

  • Recursive documentation of Python objects: just use the module dotted-path as identifier, and you get the full module docs. You don't need to inject documentation for each class, function, etc.

  • Support for documented attributes: attributes (variables) followed by a docstring (triple-quoted string) will be recognized by pytkdocs in modules, classes and even in __init__ methods.

  • Support for objects properties: pytkdocs detects if a method is a staticmethod, a classmethod, etc., it also detects if a property is read-only or writable, and more! These properties will be displayed next to the object signature by mkdocstrings.

  • Multiple docstring-styles support: almost complete support for Google-style, Numpy-style, and reStructuredText-style docstrings. Note: only RST style is supported, not the whole markup.

  • Admonition support in docstrings: blocks like Note: or Warning: will be transformed to their admonition equivalent. We do not support nested admonitions in docstrings!

  • Every object has a TOC entry: we render a heading for each object, meaning MkDocs picks them into the Table of Contents, which is nicely display by the Material theme. Thanks to mkdocstrings cross-reference ability, you can reference other objects within your docstrings, with the classic Markdown syntax: [this object][package.module.object] or directly with [package.module.object][]

  • Source code display: mkdocstrings can add a collapsible div containing the highlighted source code of the Python object.

Roadmap

See the Feature Roadmap issue on the bugtracker.

Requirements

mkdocstrings requires Python 3.6 or above.

To install Python 3.6, I recommend using pyenv.
# install pyenv
git clone https://github.com/pyenv/pyenv ~/.pyenv

# setup pyenv (you should also put these three lines in .bashrc or similar)
export PATH="${HOME}/.pyenv/bin:${PATH}"
export PYENV_ROOT="${HOME}/.pyenv"
eval "$(pyenv init -)"

# install Python 3.6
pyenv install 3.6.12

# make it available globally
pyenv global system 3.6.12

This project currently only works with the Material theme of MkDocs. Therefore, it is required that you have it installed.

pip install mkdocs-material

Installation

With pip:

python3.6 -m pip install mkdocstrings

With conda:

conda install -c conda-forge mkdocstrings

Quick usage

# mkdocs.yml
theme:
  name: "material"

plugins:
- search
- mkdocstrings

In one of your markdown files:

# Reference

::: my_library.my_module.my_class

See the Usage section of the docs for more examples!

Comments
  • jinja2.exceptions.TemplateNotFound: alias.html

    jinja2.exceptions.TemplateNotFound: alias.html

    Describe the bug

    While running mkdocs build I get an exception:

    $ mkdocs build
    INFO     -  Cleaning site directory
    INFO     -  Building documentation to directory: C:\Users\lameg\kubekind\site
    WARNING  -  mkdocstrings_handlers: 1 aliases were still unresolved after 2 iterations
    ERROR    -  mkdocstrings: Template 'alias.html' not found for 'python' handler and theme 'material'.
    ERROR    -  Error reading page 'index.md': alias.html
    Traceback (most recent call last):
      File "C:\Users\lameg\miniforge3\lib\runpy.py", line 197, in _run_module_as_main
        return _run_code(code, main_globals, None,
      File "C:\Users\lameg\miniforge3\lib\runpy.py", line 87, in _run_code
        exec(code, run_globals)
      File "C:\Users\lameg\miniforge3\Scripts\mkdocs.exe\__main__.py", line 7, in <module>
      File "C:\Users\lameg\miniforge3\lib\site-packages\click\core.py", line 1137, in __call__
        return self.main(*args, **kwargs)
      File "C:\Users\lameg\miniforge3\lib\site-packages\click\core.py", line 1062, in main
        rv = self.invoke(ctx)
      File "C:\Users\lameg\miniforge3\lib\site-packages\click\core.py", line 1668, in invoke
        return _process_result(sub_ctx.command.invoke(sub_ctx))
      File "C:\Users\lameg\miniforge3\lib\site-packages\click\core.py", line 1404, in invoke
        return ctx.invoke(self.callback, **ctx.params)
      File "C:\Users\lameg\miniforge3\lib\site-packages\click\core.py", line 763, in invoke
        return __callback(*args, **kwargs)
      File "C:\Users\lameg\miniforge3\lib\site-packages\mkdocs\__main__.py", line 192, in build_command
        build.build(config.load_config(**kwargs), dirty=not clean)
      File "C:\Users\lameg\miniforge3\lib\site-packages\mkdocs\commands\build.py", line 292, in build
        _populate_page(file.page, config, files, dirty)
      File "C:\Users\lameg\miniforge3\lib\site-packages\mkdocs\commands\build.py", line 174, in _populate_page
        page.render(config, files)
      File "C:\Users\lameg\miniforge3\lib\site-packages\mkdocs\structure\pages.py", line 175, in render
        self.content = md.convert(self.markdown)
      File "C:\Users\lameg\miniforge3\lib\site-packages\markdown\core.py", line 264, in convert
        root = self.parser.parseDocument(self.lines).getroot()
      File "C:\Users\lameg\miniforge3\lib\site-packages\markdown\blockparser.py", line 90, in parseDocument
        self.parseChunk(self.root, '\n'.join(lines))
      File "C:\Users\lameg\miniforge3\lib\site-packages\markdown\blockparser.py", line 105, in parseChunk
        self.parseBlocks(parent, text.split('\n\n'))
      File "C:\Users\lameg\miniforge3\lib\site-packages\markdown\blockparser.py", line 123, in parseBlocks
        if processor.run(parent, blocks) is not False:
      File "C:\Users\lameg\miniforge3\lib\site-packages\mkdocstrings\extension.py", line 121, in run
        html, handler, data = self._process_block(identifier, block, heading_level)
      File "C:\Users\lameg\miniforge3\lib\site-packages\mkdocstrings\extension.py", line 209, in _process_block
        rendered = handler.render(data, options)
      File "C:\Users\lameg\miniforge3\lib\site-packages\mkdocstrings_handlers\python\handler.py", line 215, in render
        template = self.env.get_template(f"{data.kind.value}.html")
      File "C:\Users\lameg\miniforge3\lib\site-packages\jinja2\environment.py", line 1010, in get_template
        return self._load_template(name, globals)
      File "C:\Users\lameg\miniforge3\lib\site-packages\jinja2\environment.py", line 969, in _load_template
        template = self.loader.load(self, name, self.make_globals(globals))
      File "C:\Users\lameg\miniforge3\lib\site-packages\jinja2\loaders.py", line 126, in load
        source, filename, uptodate = self.get_source(environment, name)
      File "C:\Users\lameg\miniforge3\lib\site-packages\jinja2\loaders.py", line 218, in get_source
        raise TemplateNotFound(template)
    jinja2.exceptions.TemplateNotFound: alias.html
    

    To Reproduce Steps to reproduce the behavior:

    git clone [email protected]:joaompinto/kubekind.git
    cd kubekind
    pip install mkdocs mkdocstrings mkdocstrings[python]
    mkdocs build
    

    Expected behavior A clear and concise description of what you expected to happen.

    Information (please complete the following information):

    • OS: Windows 10
    • mkdocstrings 0.19.0
    bug 
    opened by joaompinto 33
  • Circular dependency with `mkdocstrings-python-legacy`

    Circular dependency with `mkdocstrings-python-legacy`

    First off, great work on this project.

    We recently converted our API docs at https://docs.ibis-project.org over to mkdocstrings and are extremely happy with the results, so thank you for all the work that you do here.

    Describe the bug

    We are using poetry2nix to manage dependencies for development environments.

    poetry2nix will turn poetry.lock into nix expressions each of which maps to a single Python package.

    To do this, poetry2nix will traverse the transitive closure of the set of dependencies specified in poetry.lock. However, it is unable to do so when a project has mkdocstrings==0.18 as a dependency because mkdocstrings 0.18 depends on mkdocstrings-python-legacy which itself depends on mkdocstrings 0.18, resulting in infinite recursion.

    To Reproduce Steps to reproduce the behavior:

    1. Install nix
    2. Download the files in this gist into a directory
    3. Run nix build

    Expected behavior

    I expect this to work with poetry2nix without infinite recursion.

    Information (please complete the following information):

    • OS: NixOS
    • Browser: Brave
    • mkdocstrings version: 0.18.0
    packaging 
    opened by cpcloud 21
  • TOC broken when selecting non-modules

    TOC broken when selecting non-modules

    # API
    
    -----
    
    ::: datadog_checks.base.AgentCheck
        selection:
          members:
            - gauge
            - count
            - monotonic_count
            - rate
            - histogram
            - historate
            - service_check
            - event
    
    ::: datadog_checks.base.stubs.aggregator.AggregatorStub
        selection:
          members:
            - assert_metric
            - assert_metric_has_tag
            - assert_metric_has_tag_prefix
            - assert_service_check
            - assert_event
            - assert_all_metrics_covered
            - assert_no_duplicate_metrics
            - assert_no_duplicate_service_checks
            - assert_no_duplicate_all
            - reset
    
    ::: datadog_checks.base.stubs.datadog_agent.DatadogAgentStub
    

    Capture

    bug rendering templates:python/material 
    opened by ofek 21
  • Formatting of function signature

    Formatting of function signature

    Is your feature request related to a problem? Please describe. Currently using the library to do a bunch of API documentation. Overall, it's been great, but I wondered if we could do anything about the function signature. As it stands, it takes one line and wraps if necessary, but I was hoping for an option to format it more like how black formats functions when they're too long for one line. For example, if I have

    def my_function(*, argument1: List[int], argument2: List[int], argument3: List[int], argument4: List[int]):
    

    I might want it formatted like this in mkdocstrings:

    my_function(
        *, 
        argument1: List[int],
        argument2: List[int],
        argument3: List[int], 
        argument4: List[int]
    ):
    

    (I know, for now, the types aren't in the signature, but this might make it more readable). Along with this, I wondered if we could add functionality to make functions expandable. Thus, with the correct setup, I could see a list of all function calls, and click on one of them to expand the documentation about that function call. Would love to hear your thoughts @pawamoy, and as always, more than happy to contribute to a solution.

    feature help wanted rendering 
    opened by rossmechanic 20
  • Documentation broken for an unknown reason.

    Documentation broken for an unknown reason.

    Describe the bug The documentation is not building if I use mkdocstrings.

    To Reproduce

    1. git clone [email protected]:kunguz/odak.git
    2. cd odak
    3. mkdocs serve

    Expected behavior A running mkdocs server, which was the case until a week or a two ago, I haven't changed anything in the meantime. But various updates took place to mkdocstrings and mkdocs-material in the meantime. I can't interpret the issue from the terminal output. If I remove mkdocstrings related lines from my MD files, things works. If I revert to an older version of mkdocstrings things also work. Everything runs perfectly if I revert to an old version, specifically mkdocs-material==8.1.0 and mkdocstrings==0.17.0 with pytkdocs[numpy-style] support.

    Information

    • Ubuntu 22.04 LTS
    • Browser: Firefox 101.0 (64-bit)
    • mkdocstrings[python] version: 0.19.0
    • mkdocs version: 1.3.0

    Additional context

    $  mkdocs serve > output.txt
    INFO     -  Building documentation...
    INFO     -  Cleaning site directory
    INFO     -  The following pages exist in the docs directory, but are not included in the "nav" configuration:
      - notes/holographic_light_transport.md
      - notes/optimizing_holograms_using_odak.md
      - notes/using_metameric_loss.md
      - odak/beginning.md
      - odak/installation.md
      - odak/learn/perception/blur_loss.md
      - odak/learn/perception/make_3d_location_map.md
      - odak/learn/perception/make_eccentricity_distance_maps.md
      - odak/learn/perception/make_pooling_size_map_lod.md
      - odak/learn/perception/make_pooling_size_map_pixels.md
      - odak/learn/perception/make_radial_map.md
      - odak/learn/perception/metamer_mse_loss.md
      - odak/learn/perception/metameric_loss.md
      - odak/learn/perception/metameric_loss_uniform.md
      - odak/learn/perception/radially_varying_blur.md
      - odak/learn/perception/rgb_2_ycrcb.md
      - odak/learn/perception/spatial_steerable_pyramid.md
      - odak/learn/perception/ycrcb_2_rgb.md
      - odak/learn/wave/adjust_phase_only_slm_range.md
      - odak/learn/wave/band_limited_angular_spectrum.md
      - odak/learn/wave/calculate_amplitude.md
      - odak/learn/wave/calculate_phase.md
      - odak/learn/wave/custom.md
      - odak/learn/wave/generate_complex_field.md
      - odak/learn/wave/gerchberg_saxton.md
      - odak/learn/wave/gradient_descent.md
      - odak/learn/wave/impulse_response_fresnel.md
      - odak/learn/wave/linear_grating.md
      - odak/learn/wave/phase_gradient.md
      - odak/learn/wave/point_wise.md
      - odak/learn/wave/prism_phase_function.md
      - odak/learn/wave/produce_phase_only_slm_pattern.md
      - odak/learn/wave/propagate_beam.md
      - odak/learn/wave/quadratic_phase_function.md
      - odak/learn/wave/set_amplitude.md
      - odak/learn/wave/shift_w_double_phase.md
      - odak/learn/wave/speckle_contrast.md
      - odak/learn/wave/stochastic_gradient_descent.md
      - odak/learn/wave/transfer_function_kernel.md
      - odak/learn/wave/wavenumber.md
      - odak/tools/check_directory.md
      - odak/tools/convert_bytes.md
      - odak/tools/list_files.md
      - odak/tools/load_dictionary.md
      - odak/tools/load_image.md
      - odak/tools/resize_image.md
      - odak/tools/save_dictionary.md
      - odak/tools/save_image.md
      - odak/tools/shell_command.md
      - odak/tools/size_of_a_file.md
      - odak/wave/adaptive_sampling_angular_spectrum.md
      - odak/wave/add_phase.md
      - odak/wave/add_random_phase.md
      - odak/wave/adjust_phase_only_slm_range.md
      - odak/wave/angular_spectrum.md
      - odak/wave/band_extended_angular_spectrum.md
      - odak/wave/band_limited_angular_spectrum.md
      - odak/wave/calculate_amplitude.md
      - odak/wave/calculate_intensity.md
      - odak/wave/calculate_phase.md
      - odak/wave/double_convergence.md
      - odak/wave/electric_field_per_plane_wave.md
      - odak/wave/fraunhofer.md
      - odak/wave/fraunhofer_equal_size_adjust.md
      - odak/wave/fraunhofer_inverse.md
      - odak/wave/generate_complex_field.md
      - odak/wave/gerchberg_saxton.md
      - odak/wave/gerchberg_saxton_3d.md
      - odak/wave/impulse_response_fresnel.md
      - odak/wave/linear_grating.md
      - odak/wave/prism_phase_function.md
      - odak/wave/produce_phase_only_slm_pattern.md
      - odak/wave/propagate_beam.md
      - odak/wave/propagate_field.md
      - odak/wave/propagate_plane_waves.md
      - odak/wave/quadratic_phase_function.md
      - odak/wave/rayleigh_resolution.md
      - odak/wave/rayleigh_sommerfeld.md
      - odak/wave/rotationspeed.md
      - odak/wave/set_amplitude.md
      - odak/wave/transfer_function_kernel.md
      - odak/wave/wavenumber.md
    ERROR    -  Error reading page 'odak/learn/perception/blur_loss.md': '<' not supported between instances of 'NoneType' and 'int'
    Traceback (most recent call last):
      File "/home/kaan/.local/bin/mkdocs", line 8, in <module>
        sys.exit(cli())
      File "/usr/lib/python3/dist-packages/click/core.py", line 1128, in __call__
        return self.main(*args, **kwargs)
      File "/usr/lib/python3/dist-packages/click/core.py", line 1053, in main
        rv = self.invoke(ctx)
      File "/usr/lib/python3/dist-packages/click/core.py", line 1659, in invoke
        return _process_result(sub_ctx.command.invoke(sub_ctx))
      File "/usr/lib/python3/dist-packages/click/core.py", line 1395, in invoke
        return ctx.invoke(self.callback, **ctx.params)
      File "/usr/lib/python3/dist-packages/click/core.py", line 754, in invoke
        return __callback(*args, **kwargs)
      File "/home/kaan/.local/lib/python3.10/site-packages/mkdocs/__main__.py", line 181, in serve_command
        serve.serve(dev_addr=dev_addr, livereload=livereload, watch=watch, **kwargs)
      File "/home/kaan/.local/lib/python3.10/site-packages/mkdocs/commands/serve.py", line 63, in serve
        config = builder()
      File "/home/kaan/.local/lib/python3.10/site-packages/mkdocs/commands/serve.py", line 58, in builder
        build(config, live_server=live_server, dirty=dirty)
      File "/home/kaan/.local/lib/python3.10/site-packages/mkdocs/commands/build.py", line 292, in build
        _populate_page(file.page, config, files, dirty)
      File "/home/kaan/.local/lib/python3.10/site-packages/mkdocs/commands/build.py", line 174, in _populate_page
        page.render(config, files)
      File "/home/kaan/.local/lib/python3.10/site-packages/mkdocs/structure/pages.py", line 175, in render
        self.content = md.convert(self.markdown)
      File "/usr/lib/python3/dist-packages/markdown/core.py", line 264, in convert
        root = self.parser.parseDocument(self.lines).getroot()
      File "/usr/lib/python3/dist-packages/markdown/blockparser.py", line 90, in parseDocument
        self.parseChunk(self.root, '\n'.join(lines))
      File "/usr/lib/python3/dist-packages/markdown/blockparser.py", line 105, in parseChunk
        self.parseBlocks(parent, text.split('\n\n'))
      File "/usr/lib/python3/dist-packages/markdown/blockparser.py", line 123, in parseBlocks
        if processor.run(parent, blocks) is not False:
      File "/home/kaan/.local/lib/python3.10/site-packages/mkdocstrings/extension.py", line 121, in run
        html, handler, data = self._process_block(identifier, block, heading_level)
      File "/home/kaan/.local/lib/python3.10/site-packages/mkdocstrings/extension.py", line 195, in _process_block
        data: CollectorItem = handler.collect(identifier, options)
      File "/home/kaan/.local/lib/python3.10/site-packages/mkdocstrings_handlers/python/handler.py", line 195, in collect
        unresolved, iterations = loader.resolve_aliases(only_exported=True, only_known_modules=True)
      File "/home/kaan/.local/lib/python3.10/site-packages/griffe/loader.py", line 179, in resolve_aliases
        self.expand_wildcards(wildcards_module)
      File "/home/kaan/.local/lib/python3.10/site-packages/griffe/loader.py", line 254, in expand_wildcards
        self.expand_wildcards(member, only_known_modules, seen)  # type: ignore[arg-type]
      File "/home/kaan/.local/lib/python3.10/site-packages/griffe/loader.py", line 260, in expand_wildcards
        if new_member.name not in obj.members or obj[new_member.name].lineno < alias_lineno:
    TypeError: '<' not supported between instances of 'NoneType' and 'int'
    
    bug collector:griffe 
    opened by kaanaksit 19
  • Is there a way to parse docstrings in Cython (.pyx) files ?

    Is there a way to parse docstrings in Cython (.pyx) files ?

    I have a Cython module that I can import this way : import cython_module. Its source code is in a cython_module.pyx file, at the same level of other .py files that already work well with mkdocstrings:

    .
    ├── cython_module.pyx
    ├── predict.py
    ├── setup.py
    └── etc
    

    This cython module contains a class with a docstring:

    cdef class Model:
        """
        This is the lower-level class used for inference, it stores the model in an optimized way and features a predict method.
    
        Attributes:
            trees : The array of trees composing the model.
            nb_trees : The number of trees in the model.
        """
    
        cdef Tree* trees
        cdef uint16_t nb_trees
    

    When specifying a ::: cython_module in one of the .md files, I get this warning: WARNING - mkdocstrings.handlers.python: Couldn't read source for 'cython_module': source code not available, and in the generated doc, the only thing showed after "cython_module" is the class name ("Model"), but no docstring, nor attributes.

    Is there a way to generate documentation from docstrings in Cython files/modules ?

    Thanks!

    question 
    opened by farjasju 17
  • Dataclasses

    Dataclasses

    @pawamoy at this point I'm going to be your top issue contributer!

    I'm starting to document some of the dataclasses we use, and was hoping for a way to easily specify a dataclass and have the docs show an optional docstring with each of the parameters of the dataclass. At the moment, it just shows the unformatted repr of the dataclass. Any ideas here?

    unconfirmed collector:pytkdocs 
    opened by rossmechanic 17
  • Allow the explicit selection of members

    Allow the explicit selection of members

    Often, you'll only want to document a subset of methods & attributes. For example: https://raw.githubusercontent.com/DataDog/integrations-core/hack-a-doc/docs/developer/base/api.md

    Is that possible currently? If so, we'll switch to this from mkautodoc 😄

    cc @pawamoy

    feature configuration 
    opened by ofek 17
  • Is there any way to skip creating the markdown files and nav manually ?

    Is there any way to skip creating the markdown files and nav manually ?

    mkdocstrings supports the injection as said in docs,

    ::: my_library.my_module.my_class
    

    I also have to create the navigation.

    This is great because it gives precise control, but is there any existing way to completely generate all the pages with sane defaults?

    Like each module's docs in separate page. And links to sub or super module. Something like pdoc3 but using the material theme.

    Many thanks for your help

    question 
    opened by aahnik 16
  • Strange error

    Strange error

    Getting this:

    ERROR   -  Error reading page 'libraries/filehandlers/api.md': list index out of range 
    Traceback (most recent call last):
      File "/workspace/.pip-modules/bin/mkdocs", line 8, in <module>
        sys.exit(cli())
      File "/workspace/.pip-modules/lib/python3.7/site-packages/click/core.py", line 764, in __call__
        return self.main(*args, **kwargs)
      File "/workspace/.pip-modules/lib/python3.7/site-packages/click/core.py", line 717, in main
        rv = self.invoke(ctx)
      File "/workspace/.pip-modules/lib/python3.7/site-packages/click/core.py", line 1137, in invoke
        return _process_result(sub_ctx.command.invoke(sub_ctx))
      File "/workspace/.pip-modules/lib/python3.7/site-packages/click/core.py", line 956, in invoke
        return ctx.invoke(self.callback, **ctx.params)
      File "/workspace/.pip-modules/lib/python3.7/site-packages/click/core.py", line 555, in invoke
        return callback(*args, **kwargs)
      File "/workspace/.pip-modules/lib/python3.7/site-packages/mkdocs/__main__.py", line 134, in serve_command
        livereload=livereload
      File "/workspace/.pip-modules/lib/python3.7/site-packages/mkdocs/commands/serve.py", line 119, in serve
        config = builder()
      File "/workspace/.pip-modules/lib/python3.7/site-packages/mkdocs/commands/serve.py", line 114, in builder
        build(config, live_server=live_server, dirty=dirty)
      File "/workspace/.pip-modules/lib/python3.7/site-packages/mkdocs/commands/build.py", line 274, in build
        _populate_page(file.page, config, files, dirty)
      File "/workspace/.pip-modules/lib/python3.7/site-packages/mkdocs/commands/build.py", line 181, in _populate_page
        'page_content', page.content, page=page, config=config, files=files
      File "/workspace/.pip-modules/lib/python3.7/site-packages/mkdocs/plugins.py", line 94, in run_event
        result = method(item, **kwargs)
      File "/workspace/.pip-modules/lib/python3.7/site-packages/mkdocstrings/plugin.py", line 138, in on_page_content
        modified_lines[i] = "\n".join(renderer.render(root_object, heading))
      File "/workspace/.pip-modules/lib/python3.7/site-packages/mkdocstrings/renderer.py", line 27, in render
        self.render_object(obj, heading_level, lines)
      File "/workspace/.pip-modules/lib/python3.7/site-packages/mkdocstrings/renderer.py", line 59, in render_object
        self.render_categories(obj, heading_level + 1, lines)
      File "/workspace/.pip-modules/lib/python3.7/site-packages/mkdocstrings/renderer.py", line 80, in render_categories
        self.render_object(method, heading_level + extra_level, lines)
      File "/workspace/.pip-modules/lib/python3.7/site-packages/mkdocstrings/renderer.py", line 50, in render_object
        lines.append(f'\n??? note "Show source code in {obj.relative_file_path}"')
      File "/workspace/.pip-modules/lib/python3.7/site-packages/mkdocstrings/documenter.py", line 190, in relative_file_path
        while path_parts[-1] != file_path_parts[-1]:
    IndexError: list index out of range
    
    bug 
    opened by RDIL 15
  • How to add path for a module

    How to add path for a module

    I think this is a fairly simple question but I haven't been able to solve it. If I have my python package in a different directory than my docs folder, how do I tell mkdocstrings to look at where the python package is?

    I'm currently using the below in my .yaml file

    plugins:
        - mkdocstrings:
            handlers:
                python:
                    setup_commands:
                        - import sys
                        - sys.path.append('../')
    
    question 
    opened by sidhomj 14
  • How to include members from another package into the generated documentation

    How to include members from another package into the generated documentation

    Problem

    Hi! I have developed a few packages, let's call them package_a and package_b for simplicity. What I'd like to do is import some members from package_b into package_a and then generate the docs for package_a, however, I can't get that to work.

    In reality, the two packages are completely separate (i.e. developed in separate private repositories), but I can't even get the docs to work if they were both in the same repository.

    Example

    Folder structure:

    .
    ├── docs
    │   ├── index.md
    │   └── mkdocs.yml
    └── src
        ├── package_a
        │   └── __init__.py
        └── package_b
            └── __init__.py
    

    mkdocs.yaml file:

    site_name: My Awesome Packages
    docs_dir: .
    site_dir: ../site
    remote_branch: gh-pages
    nav:
      - Home: index.md
    theme:
      name: material
      palette:
    
        # Palette toggle for light mode
        - scheme: default
          primary: teal
          toggle:
            icon: material/brightness-7
            name: Switch to dark mode
    
        # Palette toggle for dark mode
        - scheme: slate
          primary: teal
          toggle:
            icon: material/brightness-4
            name: Switch to light mode
    plugins:
    - search
    - same-dir
    - mkdocstrings:
        handlers:
          python:
            paths: [../src]
            import:
            - https://docs.python.org/3/objects.inv
            options:
              filters:
              - "!^_[^_]"
              - "!__version__"
              - "!__all__"
              heading_level: 1
              show_root_heading: true
              show_category_heading: true
              merge_init_into_class: true
              show_if_no_docstring: true
              separate_signature: true
              group_by_category: true
              members_order: alphabetical
              annotations_path: brief
              show_signature_annotations: true
    watch:
    - ../src
    - .
    

    Installed dependencies (some of them are unused in this example, but I use it in my full use case):

    mkdocs==1.4.2
    mkdocs-gen-files==0.4.0
    mkdocs-literate-nav==0.5.0
    mkdocs-material==9.0.2
    mkdocs-same-dir==0.1.2
    mkdocs-section-index==0.3.4
    mkdocstrings==0.19.1
    mkdocstrings-python==0.8.3
    

    The contents of docs/index.md:

    # Docs
    
    ::: package_a
    

    The contents of my packages:

    # src/package_a/__init__.py
    """Package A - does stuff"""
    
    from package_b import bar
    
    def foo(x: int) -> str:
        return str(x)
    
    
    __all__ = ["foo", "bar"]
    
    # src/package_b/__init__.py
    """Package B - does some other stuff"""
    def bar(x: str) -> int:
        return int(x)
    
    __all__ = ["bar"]
    

    What the docs page looks like: image

    Ideally, I'd like the page to show the documentation for both foo and bar.

    What I tried

    I tried looking through the code and I found that changing this line to have external=True seems to work, although I'm not sure if it doesn't break anything else: image

    Is there a more "proper" way to achieve the same thing? Thanks!

    question 
    opened by vstrimaitis 0
  • If two different handlers are used in one document, the jinja env is not updated

    If two different handlers are used in one document, the jinja env is not updated

    Found another issue/question with what I was trying to do with a custom handler.

    If one document has two identifiers that use different handlers; only the first one's env is updated. My templates error out because the default mkdocstring filters are missing (highlight, heading or convert_markdown) don't exist in the second handler yet and instead I only have the built-in jinja filters and the any filter that is added when the env is initialized.

    ::: mkdocstrings_handlers.custom_handler.other_module.AccessTypes
        handler: python
    
    ::: demo.custom_identifier.stuff
        handler: custom_handler
    

    It looks like these few lines are the offenders and I'm curious if there is a drawback to updating it every time, updating the env on init or make the _updated_env a part of the handler and not the extension? Commenting out self._updated_env = True is enough to resolve this issue.

            if not self._updated_env:
                log.debug("Updating renderer's env")
                handler._update_env(self.md, self._config)  # noqa: WPS437 (protected member OK)
                self._updated_env = True
    
    unconfirmed 
    opened by jdpatt 0
  • Expose Config to enable handling non-css files during collection or render

    Expose Config to enable handling non-css files during collection or render

    Like everyone great tool that I use to document my python code. I've been playing around with a custom handler based off your template handler to document some internal file formats/code that are not python and have a few questions.

    I am using another tool to generate some image diagrams. Doing that in the render() method makes mkdocs serve go into an infinite loop after you click a page since it sees a file change in the docs_dir, regenerates, sees lots of image files change again then loops. I can do a few things but are looking to your suggestion on the best or if I have missed an easier path.

    Use mkdocs serve --dirtyreload [Current Solution]

    Not great since an update to that file doesn't necessarily trigger updating these diagrams since they are different files. So while I'm not infinitely looping, I'm not rendering the latest and greatest when serving. Build works as expected.

    Use a similar recipe to automatic code pages with mkdocs-gen-files. [Rejected]

    Since this doesn't know what identifiers will be collected, I have to generate a lot of images that may never be used. I also have no guarantees when rendering that the file actually exists since I don't know the site_dir at the handler scope.

    mkdocstrings change to expose mkdocs config to handler

    Currently, it looks like the configuration is stripped down before passing to the handler. A potential solution to give me access to the mkdocs configuration object and ultimate configurability by passing that to the handler? This could allow collect(), render(), and teardown() have some knowledge about the current mkdocs configuration including where the site_dir is to copy these files directly into it. Looking at the python and crystal handlers, neither use site_name.

    plugin.py:168

            extension_config = {
                "site_name": config["site_name"],  # Change this to "mkdocs_config": config,
                "config_file_path": config["config_file_path"],
                "theme_name": theme_name,
                "mdx": config["markdown_extensions"],
                "mdx_configs": config["mdx_configs"],
                "mkdocstrings": self.config,
                # "mkdocs_config": config, #  Or add as a new item to not break existing code.
            }
            self._handlers = Handlers(extension_config)
    

    mkdocstrings change to add a extra_files method during the on_env event. [Rejected]

    Just like the handler.extra_css, add an attribute to BaseHandler that is a iterable of paths to copy to where ever the site_dir may be. I can populate extra_files during rendering or collecting and if one errors out for any reason, react to it in the rendering.

    if self._handlers:
        css_content = "\n".join(handler.extra_css for handler in self.handlers.seen_handlers)
        write_file(css_content.encode("utf-8"), os.path.join(config["site_dir"], self.css_filename))
    
        for handler in self.handlers.seen_handlers:
            for filepath in handler.extra_files:
                copy_file(filepath, os.path.join(config["site_dir"])
    

    If either of these two changes are favorable, happy to open a PR as such. My preference would be exposing the mkdocs configuration but the second option has better "guard rails" for users.


      - mkdocstrings:
          handlers:
            python:
              paths: [src]
              import:
                - https://docs.python.org/3/objects.inv
                - https://mkdocstrings.github.io/objects.inv
            my_custom_handler:
              paths:
                - where to look for these files.
    
    • mkdocstrings version: 0.19.1
    question 
    opened by jdpatt 3
  • Hide class docstring

    Hide class docstring

    Hi

    Thanks for a great package!

    I am trying to create sections in the docs for a class LCA . In the example below I first document the class and it's attributes from the class docstr. Subsequently methods starting with "set", "plot" and finally the remaining public methods are documented.

    With my current approach the class docstr on LCA gets repeated in each section. Is there a way to avoid the class docstr being included e.g. options.self: no. Alternatively, is there a different pattern I could use - I would like to avoid adding and sorting all methods manually.

    Happy holidays to you all. Cheers, Jacob

    ::: src.analyses.LCA
        options: 
            members: no
    
    ## `set` methods
    
    Some general description of set methods
    
    ::: src.analyses.LCA
        options:
          show_root_heading: false
        selection: 
            filters: 
                - "^set"
    
    ## `plot` methods
    
    Some general description of plot methods
    
    ::: src.analyses.LCA
        options:
          show_root_heading: false
        selection: 
            filters: 
                - "^plot"
    
    ## Other methods
    
    ::: src.analyses.LCA
        options:
          show_root_heading: false
        selection: 
            filters:
                - "!^_"
                - "!^set"
                - "!^plot"
    
    
    feature 
    opened by mrsonne 3
  • Handle Google style docstrings for Python properties

    Handle Google style docstrings for Python properties

    Hey, thank you so much for your work on mkdocstrings!

    Currently, mkdocstrings has support for methods that have docstrings that follow the Google style, but sadly it does not have support for properties (@property) that follow the Google style for Python docstrings.

    So, currently, I have to do something like:

    class MyClass:
        # ...
        @property
        def my_int_property(self) -> int:
            """My brief description here.
    
            Returns:
                int: A typically redundant description here.
            """
    

    Ideally, I would just do something like

    class MyClass:
        # ...
        @property
        def my_int_property(self) -> int:
            """int: My brief description here."""
    

    In a perfect world, mkdocstrings would even pick up the name of the return value from the property name itself!

    feature 
    opened by rodrigogiraoserrao 3
  • Adjust license entry

    Adjust license entry

    Fixes

    , line 85, in validate_pep621
          raise PEP621ValidationError(validator.errors)
      pdm.pep517.exceptions.PEP621ValidationError: {'license': ['none or more than one rule validate', {'oneof definition 0': ['must be of dict type'], 'oneof definition 1': ['must be of dict type']}]}
    
    opened by fabaff 1
Releases(0.19.0)
  • 0.19.0(May 28, 2022)

    Highlights

    We decided to deprecate a few things to pave the way towards a more stable code base, bringing us closer to a v1.

    • Selection and rendering options are now combined into a single options key. Using the old keys will emit a deprecation warning.
    • The BaseCollector and BaseRenderer classes are deprecated in favor of BaseHandler, which merges their functionality. Using the old classes will emit a deprecation warning.

    New versions of the Python handler and the legacy Python handler were also released in coordination with mkdocstrings 0.19. See their respective changelogs: python, python-legacy. Most notably, the Python handler gained the members and filters options that prevented many users to switch to it.

    mkdocstrings stopped depending directly on the legacy Python handler. It means you now have to explicitely depend on it, directly or through the extra provided by mkdocstrings, if you want to continue using it.

    Packaging / Dependencies

    • Stop depending directly on mkdocstrings-python-legacy (9055d58 by TimothĂ©e Mazzucotelli). Issue #376

    Features

    Code Refactoring

    • Support options / deprecated options mix-up (7c71f26 by TimothĂ©e Mazzucotelli).
    • Deprecate watch feature in favor of MkDocs' built-in one (c20022e by TimothĂ©e Mazzucotelli).
    • Log relative template paths if possible, instead of absolute (91f5f83 by TimothĂ©e Mazzucotelli).
    • Deprecate selection and rendering YAML keys (3335310 by TimothĂ©e Mazzucotelli). PR #420
    • Deprecate BaseCollector and BaseRenderer (eb822cb by TimothĂ©e Mazzucotelli). PR #413
    Source code(tar.gz)
    Source code(zip)
  • 0.18.0(Feb 6, 2022)

    Highlights

    • Python 3.6 support is dropped.
    • We provide a new, experimental Python handler based on Griffe. This new handler brings automatic cross-references for every annotation in your code, including references to third-party libraries' APIs if they provide objects inventories and you explicitely load them in mkdocs.yml. See migration notes in the documentation.
    • The "legacy" Python handler now lives in its own repository at https://github.com/mkdocstrings/python-legacy.

    Packaging / Dependencies

    • Add Crystal extra, update Python extras versions (b8222b0 by TimothĂ©e Mazzucotelli). PR #374
    • Update autorefs to actually required version (fc6c7f6 by TimothĂ©e Mazzucotelli).
    • Drop Python 3.6 support (7205ac6 by TimothĂ©e Mazzucotelli).

    Features

    • Allow unwrapping the <p> tag in convert_markdown filter (5351fc8 by Oleh Prypin). PR #369
    • Support handlers spanning multiple locations (f42dfc6 by TimothĂ©e Mazzucotelli). PR #355

    Code Refactoring

    • Prefix logs with the package name only (6c2b734 by TimothĂ©e Mazzucotelli). PR #375
    • Extract the Python handler into its own repository (74371e4 by TimothĂ©e Mazzucotelli). PR #356
    • Support Jinja2 3.1 (b377227 by TimothĂ©e Mazzucotelli). Issue #360, PR #361
    • Find templates in new and deprecated namespaces (d5d5f18 by TimothĂ©e Mazzucotelli). PR #367
    • Support loading handlers from the mkdocstrings_handlers namespace (5c22c6c by TimothĂ©e Mazzucotelli). PR #367
    Source code(tar.gz)
    Source code(zip)
  • 0.17.0(Jan 15, 2022)

    0.17.0 - 2021-12-27

    Compare with 0.16.2

    Features

    Bug Fixes

    • Do minimum work when falling back to re-collecting an object to get its anchor (f6cf570 by TimothĂ©e Mazzucotelli). Issue #329, PR #330

    Code Refactoring

    Source code(tar.gz)
    Source code(zip)
  • 0.16.0(Sep 21, 2021)

    Features

    Bug Fixes

    • Don't render empty code blocks for missing type annotations (d2e9e1e by Oleh Prypin).
    • Fix custom handler not being used (6dcf342 by TimothĂ©e Mazzucotelli). Issue #259, PR #263
    • Don't hide setup_commands errors (92418c4 by Gabriel VĂźjială). PR #258

    Code Refactoring

    • Move writing extra files to an earlier stage in the build (3890ab5 by Oleh Prypin). PR #275
    Source code(tar.gz)
    Source code(zip)
Dev Centric Tools for Mkdocs Based Documentation

docutools MkDocs Documentation Tools For Developers This repo is providing a set of plugins for mkdocs material compatible documentation. It is meant

Axiros GmbH 14 Sep 10, 2022
Automatic links from code examples to reference documentation

sphinx-codeautolink Automatic links from Python code examples to reference documentation at the flick of a switch! sphinx-codeautolink analyses the co

Felix Hildén 41 Dec 17, 2022
A Material Design theme for MkDocs

A Material Design theme for MkDocs Create a branded static site from a set of Markdown files to host the documentation of your Open Source or commerci

Martin Donath 12.3k Jan 4, 2023
An MkDocs plugin to export content pages as PDF files

MkDocs PDF Export Plugin An MkDocs plugin to export content pages as PDF files The pdf-export plugin will export all markdown pages in your MkDocs rep

Terry Zhao 266 Dec 13, 2022
An MkDocs plugin that simplifies configuring page titles and their order

MkDocs Awesome Pages Plugin An MkDocs plugin that simplifies configuring page titles and their order The awesome-pages plugin allows you to customize

Lukas Geiter 282 Dec 28, 2022
Generate a single PDF file from MkDocs repository.

PDF Generate Plugin for MkDocs This plugin will generate a single PDF file from your MkDocs repository. This plugin is inspired by MkDocs PDF Export P

null 198 Jan 3, 2023
MkDocs plugin for setting revision date from git per markdown file

mkdocs-git-revision-date-plugin MkDocs plugin that displays the last revision date of the current page of the documentation based on Git. The revision

Terry Zhao 48 Jan 6, 2023
A tool that allows for versioning sites built with mkdocs

mkdocs-versioning mkdocs-versioning is a plugin for mkdocs, a tool designed to create static websites usually for generating project documentation. mk

Zayd Patel 38 Feb 26, 2022
MkDocs Plugin allowing your visitors to *File > Print > Save as PDF* the entire site.

mkdocs-print-site-plugin MkDocs plugin that adds a page to your site combining all pages, allowing your site visitors to File > Print > Save as PDF th

Tim Vink 67 Jan 4, 2023
Yet Another MkDocs Parser

yamp Motivation You want to document your project. You make an effort and write docstrings. You try Sphinx. You think it sucks and it's slow -- I did.

Max Halford 10 May 20, 2022
Mkdocs obsidian publish - Publish your obsidian vault through a python script

Mkdocs Obsidian Mkdocs Obsidian is an association between a python script and a

Mara 49 Jan 9, 2023
Plugins for MkDocs.

Plugins for MkDocs and Python Markdown pip install neoteroi-mkdocs This package includes the following plugins and extensions: Name Description Type m

null 35 Dec 23, 2022
Soccerdata - Efficiently scrape soccer data from various sources

SoccerData is a collection of wrappers over soccer data from Club Elo, ESPN, FBr

Pieter Robberechts 195 Jan 4, 2023
Main repository for the Sphinx documentation builder

Sphinx Sphinx is a tool that makes it easy to create intelligent and beautiful documentation for Python projects (or other documents consisting of mul

null 5.1k Jan 2, 2023
A curated list of awesome tools for Sphinx Python Documentation Generator

Awesome Sphinx (Python Documentation Generator) A curated list of awesome extra libraries, software and resources for Sphinx (Python Documentation Gen

Hyunjun Kim 831 Dec 27, 2022
API Documentation for Python Projects

API Documentation for Python Projects. Example pdoc -o ./html pdoc generates this website: pdoc.dev/docs. Installation pip install pdoc pdoc is compat

mitmproxy 1.4k Jan 7, 2023
Literate-style documentation generator.

888888b. 888 Y88b 888 888 888 d88P 888 888 .d8888b .d8888b .d88b. 8888888P" 888 888 d88P" d88P" d88""88b 888 888 888

Pycco 808 Dec 27, 2022
Main repository for the Sphinx documentation builder

Sphinx Sphinx is a tool that makes it easy to create intelligent and beautiful documentation for Python projects (or other documents consisting of mul

null 5.1k Jan 4, 2023
Project documentation with Markdown.

MkDocs Project documentation with Markdown. View the MkDocs documentation. Project release notes. Visit the MkDocs wiki for community resources, inclu

MkDocs 15.6k Jan 2, 2023