Giter Site home page Giter Site logo

mkdocstrings / python Goto Github PK

View Code? Open in Web Editor NEW
172.0 4.0 32.0 3.84 MB

A Python handler for mkdocstrings.

Home Page: https://mkdocstrings.github.io/python

License: ISC License

Makefile 0.22% Python 40.75% HTML 9.55% CSS 1.68% Dockerfile 0.06% Jinja 47.73% Shell 0.01%
python mkdocstrings-handler mkdocstrings mkdocs autodoc documentation python-documentation

python's Introduction

mkdocstrings-python

A Python handler for mkdocstrings.

ci documentation pypi version gitpod gitter


The Python handler uses Griffe to collect documentation from Python source code. The word "griffe" can sometimes be used instead of "signature" in French. Griffe is able to visit the Abstract Syntax Tree (AST) of the source code to extract useful information. It is also able to execute the code (by importing it) and introspect objects in memory when source code is not available. Finally, it can parse docstrings following different styles.

Installation

You can install this handler as a mkdocstrings extra:

# PEP 621 dependencies declaration
# adapt to your dependencies manager
[project]
dependencies = [
    "mkdocstrings[python]>=0.18",
]

You can also explicitly depend on the handler:

# PEP 621 dependencies declaration
# adapt to your dependencies manager
[project]
dependencies = [
    "mkdocstrings-python",
]

Preview

mkdocstrings_python_gif

Features

  • Data collection from source code: collection of the object-tree and the docstrings is done thanks to Griffe.

  • Support for type annotations: Griffe collects your type annotations and mkdocstrings uses them to display parameter types or return types. It is even able to automatically add cross-references to other objects from your API, from the standard library or third-party libraries! See how to load inventories to enable it.

  • Recursive documentation of Python objects: just use the module dotted-path as an 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 Griffe in modules, classes and even in __init__ methods.

  • Multiple docstring-styles support: common support for Google-style, Numpydoc-style, and Sphinx-style docstrings. See Griffe's documentation on docstrings support.

  • Admonition support in Google 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 displayed 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.

python's People

Contributors

andrewguenther avatar antoined avatar blueglassblock avatar bswck avatar fasterspeeding avatar gilfree avatar hnasar avatar hofaflo avatar melissawm avatar oprypin avatar pawamoy avatar romain-intel avatar ssbarnea avatar thatlittleboy avatar veghdev avatar viicos avatar waylan avatar whiteapfel 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  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  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  avatar  avatar

python's Issues

Summary Tables

Hello, and thanks for the brilliant work. I was wondering if there is an option to make summary tables similar to here as opposed to what is currently available in mkdocstrings here

A summary table, make a summary of all the entries of that page (i.e. classes, APIs, etc.) at the top of the page rather than a long list of detailed APIs immediately in the beginning, which could startle the users.

show all the source code automatically inside a package in a single page

Is your feature request related to a problem? Please describe.
With the old legacy python handler, we set only the root package, for example, :::demo, then all the sub-modules, files inside of the demo package will be discovered and displayed automatically in this single page.

Now with the new python handler, mkdocs build doesn't raise any error, but when I preveiw the result with mkdocs serve, it renders just a blank page.

But if I go deeper to the file level, it will render it, but just only one python file each time, for eample :::demo.sub_package1.sub_file1

Describe the solution you'd like
make backward compatible with an option in mkdocs.yml config file, otherwise, with the new version, we should create as many pages or line sto specifiy each python source code file one by one, and with previous legacy python handler, we just need to specify the root package name like :::demo, this save us a lot of time, because we have many source code files.

Describe alternatives you've considered

Additional context

Display overwritten/inherited methods in sublcasses

Is your feature request related to a problem? Please describe.
Consider the following scenario. We have a base class called A and one or multiple derived classes B1, B2, ... The base class A implements a method func. After building the doc, we can reference this method with [path.to.A.func][]. Let's further consider that B1 and the others overwrite func and we would like to reference B1.func in the doc of B2.func. However, if I am not completely mistaking, we can not do this since they are not displayed in the doc page because func is already defined in A.

Describe the solution you'd like
An option just like the ones listed here, e.g. show_inherited_members, that prints the members of subclasses, and provides anchors to them.

Describe alternatives you've considered
There are none.

Non-Primitive Return Types are Incorrectly Formatted

Describe the bug
mkdocstrings-python handler does not correctly format non-primitive return types in the generated documentation table, although this functionality remains correct for native types such as str, int, float, etc.

This is in contrast to the legacy mkdocstrings-python-legacy handler that generates the return types correctly.

To Reproduce
Have a return type of typing.List (from typing package), for example, and notice that the generated documentation table is incorrect. It will have a description of "typing.List {user-added docstrings}", and optionally also gets incorrectly treated as "Name".

Expected behavior
Return type is not repeated and not considered as name, just like in mkdocstrings-python-legacy.

Screenshots
mkdocstrings_python_return_issue

System (please complete the following information):

  • mkdocstrings-python version: 0.8.3
  • Python version: 3.8.15
  • OS: Linux

Additional context
An example of the incorrectly generated documentation table can be found here.

Wrong links for inventory imports

When adding an inventory file via the config file, the resulting generating links have the url of the inv file prepended.
So in my case I have:

plugins:
    - mkdocstrings:
        default_handler: python
        handlers:
          python:
            import:
              - url: https://raw.githubusercontent.com/phil65/PrettyQt/master/docs/qt6.inv
                domains: [std, py]

but in generated docs, the references link e.g. to https://raw.githubusercontent.com/phil65/PrettyQt/master/docs/https://doc.qt.io/qtforpython/PySide6/QtBluetooth/QBluetoothAddress.html#PySide6.QtBluetooth.PySide6.QtBluetooth.QBluetoothAddress

(see here for example: https://phil65.github.io/PrettyQt/api/bluetooth.html )

Is it a bug or am I missing something?

It would also be nice to be able to use local .inv files, it seems as if this is not possible right now.

Thank you!

Show __init__ exports

Problem

The __init__.py is sometimes used to re-export functions and classes defined within sub-modules, generally for visibility within the library and also with the auto-completion. It would be nice if the documentation showed this as well.

Solution

Ideally, I would like an option that shows explicit imports/re-exports located within __init__.py. Based on other linting conventions, the way this is done is to be explicit with an as even if it is tautological, though may not always be.

# Explicit import and re-export without changing the name
from .foo import Bar as Bar
# Explicit import and re-export with a name change
from .foo import Baz as FooBaz

As for the implementation, I like the way Rust documentation shows re-exports in a section dedicated for re-exports. This makes it clear that the class or function is defined elsewhere but has been made available within the current namespace. Here's an example from the popular Clap library:

https://docs.rs/clap/latest/clap/#reexports

Alternatives

I tried looking at the options available, but could not identify anything that would provide the functionality I need.

Another alternative would be to have the gen-files script handle this, but the implementation does not appear to be easy.

Extra

The ability to document re-exports I think could be implemented with the following options if there might be a need for that, though I struggle to see the use-case for any of them other than explicit-init.

  • explicit-init: This would only document explicit re-exports (i.e., ones that use the as notation) within __init__.py files.
  • explicit-all: This would document explicit re-exports, but within any Python file.
  • implicit-init: This would document all imports (whether they use the explicit as notation or not), but only within __init__.py
  • implicit-all: As with implicit-init, but for all files.

Properties are rendered with parens

Describe the bug
@property's are rendered with trailing () which makes them look like functions.

To Reproduce

class Example:
    @property
    def foobar(self):
        """
        Return the value of the foobar property
        """
        return 42

Expected behavior
I expect the heading in the API docs to be just foobar but it is rendered as foobar()

System (please complete the following information):

mkdocs==1.2.3
mkdocs-autorefs==0.4.1
mkdocs-material==7.3.4
mkdocs-material-extensions==1.0.3
mkdocstrings==0.18.1
mkdocstrings-python==0.6.6

Parameters and Returns headings are not visible

Is your feature request related to a problem? Please describe.

"Parameters" and "Returns" headings are simple HTML paragraphes without any CSS class. They currently just look like plain text and there is no way to style them.

Describe the solution you'd like

The easiest solution is to assign a CSS class to these headings such that we can style them arbitrarily.
Additionally, it would be better if they were actual HTML headings (and we could choose the level).
The colons also look rather unpolished.

Suggestion: Add option to expand Literals

The old python handler "expanded" Literals and was showing every single value (for method parameter types for example), in this new one it only shows the name of the Literal. Would be great to have that option for the now handler, too.

Wrong URL for external package cross-reference

Describe the bug
A cross reference to torch.utils.data.DataLoader is rendered with incorrect links.
Screen Shot 2022-08-04 at 12 29 12 PM
Here, torch points to https://pytorch.org/docs/1.10.1/data.html#module-torch.utils.data. data and DataLoader point to correct URLs.

I opened up the objects.inv file provided by PyTorch with Inventory.parse_sphinx and found that it does not have entries for torch and torch.utils. In such a case, I think torch should not point to anything like how torch.utils is not linked to anything.

To Reproduce

# test.py
import torch.utils.data

class MyDataLoader(torch.utils.data.DataLoader):
    pass
<!-- docs/index.md -->
::: test.MyDataLoader
# mkdocs.yml
site_name: Test

theme:
  name: material

plugins:
  - mkdocstrings:
      handlers:
        python:
          import:
            - https://pytorch.org/docs/1.10.1/objects.inv

nav:
  - Home: index.md

System:

  • mkdocstrings-python version: 0.7.1
  • Python version: 3.9.12
  • OS: MacOS

ValueError: 'restructured-text' is not a valid Parser using new `python` handler

Describe the bug
When building the mkdocs site using the new python handler, I get an exception saying ValueError: 'restructured-text' is not a valid Parser. This does work when using the python-legacy handler

To Reproduce
Steps to reproduce the behavior:

  1. Run pip install mkdocstrings[python]
  2. Run mkdocs serve

Expected behavior
Mkdocs builds successfully and parses restructured-text docstrings

System (please complete the following information):

mkdocs==1.3.0
mkdocs-autorefs==0.4.1
mkdocs-jupyter==0.20.1
mkdocs-material==8.2.11
mkdocs-material-extensions==1.0.3
mkdocstrings==0.19.0
mkdocstrings-python==0.7.1

I assume this relates to the "Note that..." here: https://mkdocstrings.github.io/handlers/overview/#about-the-python-handlers

Show return type annotation when show_signature_annotations = true

Describe the solution you'd like

When setting:

plugins:
  - search
  - mkdocstrings:
      handlers:
        python:
          rendering:
            show_signature_annotations: true

It would be helpful if this also rendered the return type (e.g -> int)

Screen Shot 2022-02-22 at 8 10 49 AM

This is the common, concise way that Python developers are used to reading types.

Describe alternatives you've considered

An extra configuration option, but I don't think that is necessary.

Default values are not displayed for types other than string

Describe the bug
Using type hints and enabling show_signature_annotations displays each parameters type correctly, but not default value unless its a string.

To Reproduce
Steps to reproduce the behavior:

  1. Define a method such as def foo(a: str = 'hello', b: int = 10, c: bool = False, d: str = 'world') -> None
  2. Enableshow_signature_annotations in your mkdocs.yml:
plugins:
  - mkdocstrings:
      handlers:
        python:
          rendering:
            show_signature_annotations: True
  1. Observe in the generated docs only the string fields default values are displayed (ie a and d).

System (please complete the following information):

  • mkdocs versions:
mkdocs==1.2
mkdocstrings==0.18.1
mkdocstrings-python==0.6.6
  • Python version: 3.7
  • OS: Linux

Numpy Methods for class docstrings are not supported

Describe the bug
Using the numpy docs style to specify a Methods section for class methods is not parsed into a table, unlike Attributes, for example. https://numpydoc.readthedocs.io/en/latest/format.html#class-docstring

To Reproduce

"""Blah blah blah...

Attributes
----------
closed: bool
    Blah blah blah...

Methods
-------
close()
    Blah blah blah...
"""

Expected behavior
Docstring is parsed correctly into a table.

Screenshots
Attributes is correctly parsed into a table, however, the Methods is appearing as regular text with no formatting.

System

  • mkdocstrings-python version: 0.7.1
  • Python version: 3.10.4
  • OS: Windows

Additional context
I am not sure whether the numpy style guide specifically says that type hints can also be used in the Methods section but noting this here just in case you can as well.

Would that look like this?

"""
Methods
-------
close() -> None
    Blah blah blah...
"""

Evaluate signature-changing decorators

Is your feature request related to a problem? Please describe.
My issue with this handler is sort of reverse of e.g. mkdocstrings/mkdocstrings#162, mkdocstrings/mkdocstrings#308.

I have a decorator that overrides the wrapped function's __annotations__ and __doc__. But since the new griffe parser doesn't evaluate modules, mkdocstrings cannot pick up those, making it impossible to use it with signature-changing decorators.

Describe the solution you'd like
Make it maybe possible to evaluate certain decorators during parsing.

Describe alternatives you've considered
The old python-legacy handler works fine in this regard (although it has other issues which prevent me from using it).

ERROR - mkdocstrings: script could not be found

Describe the bug
I use mkdocstrings + mkdocs-material to document my package. However, when I try to build or serve the documentation, mkdocstrings cannot find my modules.

I end with the following error :

❯ mkdocs serve
INFO     -  Building documentation...
INFO     -  Cleaning site directory
ERROR    -  mkdocstrings: azure_helper.steps.create_aml_env could not be found
ERROR    -  Error reading page 'steps/create_aml_env.md':
ERROR    -  Could not collect 'azure_helper.steps.create_aml_env'

Aborted with a BuildError!

To Reproduce
Steps to reproduce the behavior:

  1. Go to https://github.com/Klimorg/azure-mlops-helper and clone the repo,
  2. Create a venv and install the package via python -m install -e . --no-cache-dir,
  3. Install doc requirements python -m pip install requirements-doc.txt
  4. Run command mkdocs serve
  5. See error

Expected behavior
The documentation should be build, mkdocs should find my modules and catch the dosctrings.

According to https://mkdocstrings.github.io/python/usage/#finding-modules it seems I am in this situation : "mkdocs.yml in root, package in root "

plugins:
    - search:
          lang: fr
    - mkdocstrings:
        handlers:
            python:
                paths: [.]  # actually not needed, default

Screenshots
Here is a screenshot to see my package config.

mkdocstrings_bug

System (please complete the following information):

mike==1.1.2
mkdocs==1.3.1
mkdocs-material==8.3.9
mkdocstrings==0.19.0
mkdocstrings-python==0.7.1
  • Python version: 3.8
  • OS:Ubuntu 20.4

Additional context
Add any other context about the problem here.

Using reexported types in docstrings throws error on collection (griffe.exceptions.AliasResolutionError: Could not resolve polars)

Describe the bug
If I reexport an external library through one file and use the types from that reexported library in another file, it will break with a griffe.exceptions.AliasResolutionError.
This might be a feature requests, but I wasn't sure.

To Reproduce
Given a package called docstring_thing and two files like this:

# b.py
import polars as polars
# a.py
from docstring_thing.b import polars 

def my_func(input: polars.LazyFrame) -> polars.LazyFrame:
    """
    Args:
        input: The first parameter.

    Returns:
        The return value.
    """
    pass

mkdocs serve will break with griffe.exceptions.AliasResolutionError: Could not resolve polars

Full output
INFO     -  Building documentation...
INFO     -  Cleaning site directory
ERROR    -  Error building page 'index.md': Could not resolve polars
Traceback (most recent call last):
  File "/home/sras/.cache/pypoetry/virtualenvs/docstring-thing-Gq5GOpo2-py3.10/lib/python3.10/site-packages/mkdocs_autorefs/plugin.py", line 78, in _get_item_url
    return self._url_map[identifier]
KeyError: 'docstring_thing.b.polars.LazyFrame'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/home/sras/.cache/pypoetry/virtualenvs/docstring-thing-Gq5GOpo2-py3.10/lib/python3.10/site-packages/griffe/dataclasses.py", line 1111, in _resolve_target
    resolved = self.modules_collection[self.target_path]
  File "/home/sras/.cache/pypoetry/virtualenvs/docstring-thing-Gq5GOpo2-py3.10/lib/python3.10/site-packages/griffe/mixins.py", line 27, in __getitem__
    return self.members[parts[0]]  # type: ignore[attr-defined]
KeyError: 'polars'

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "/home/sras/.cache/pypoetry/virtualenvs/docstring-thing-Gq5GOpo2-py3.10/bin/mkdocs", line 8, in <module>
    sys.exit(cli())
  File "/home/sras/.cache/pypoetry/virtualenvs/docstring-thing-Gq5GOpo2-py3.10/lib/python3.10/site-packages/click/core.py", line 1130, in __call__
    return self.main(*args, **kwargs)
  File "/home/sras/.cache/pypoetry/virtualenvs/docstring-thing-Gq5GOpo2-py3.10/lib/python3.10/site-packages/click/core.py", line 1055, in main
    rv = self.invoke(ctx)
  File "/home/sras/.cache/pypoetry/virtualenvs/docstring-thing-Gq5GOpo2-py3.10/lib/python3.10/site-packages/click/core.py", line 1657, in invoke
    return _process_result(sub_ctx.command.invoke(sub_ctx))
  File "/home/sras/.cache/pypoetry/virtualenvs/docstring-thing-Gq5GOpo2-py3.10/lib/python3.10/site-packages/click/core.py", line 1404, in invoke
    return ctx.invoke(self.callback, **ctx.params)
  File "/home/sras/.cache/pypoetry/virtualenvs/docstring-thing-Gq5GOpo2-py3.10/lib/python3.10/site-packages/click/core.py", line 760, in invoke
    return __callback(*args, **kwargs)
  File "/home/sras/.cache/pypoetry/virtualenvs/docstring-thing-Gq5GOpo2-py3.10/lib/python3.10/site-packages/mkdocs/__main__.py", line 234, in serve_command
    serve.serve(dev_addr=dev_addr, livereload=livereload, watch=watch, **kwargs)
  File "/home/sras/.cache/pypoetry/virtualenvs/docstring-thing-Gq5GOpo2-py3.10/lib/python3.10/site-packages/mkdocs/commands/serve.py", line 83, in serve
    builder(config)
  File "/home/sras/.cache/pypoetry/virtualenvs/docstring-thing-Gq5GOpo2-py3.10/lib/python3.10/site-packages/mkdocs/commands/serve.py", line 76, in builder
    build(config, live_server=live_server, dirty=dirty)
  File "/home/sras/.cache/pypoetry/virtualenvs/docstring-thing-Gq5GOpo2-py3.10/lib/python3.10/site-packages/mkdocs/commands/build.py", line 329, in build
    _build_page(file.page, config, doc_files, nav, env, dirty)
  File "/home/sras/.cache/pypoetry/virtualenvs/docstring-thing-Gq5GOpo2-py3.10/lib/python3.10/site-packages/mkdocs/commands/build.py", line 234, in _build_page
    output = config.plugins.run_event('post_page', output, page=page, config=config)
  File "/home/sras/.cache/pypoetry/virtualenvs/docstring-thing-Gq5GOpo2-py3.10/lib/python3.10/site-packages/mkdocs/plugins.py", line 520, in run_event
    result = method(item, **kwargs)
  File "/home/sras/.cache/pypoetry/virtualenvs/docstring-thing-Gq5GOpo2-py3.10/lib/python3.10/site-packages/mkdocs_autorefs/plugin.py", line 205, in on_post_page
    fixed_output, unmapped = fix_refs(output, url_mapper)
  File "/home/sras/.cache/pypoetry/virtualenvs/docstring-thing-Gq5GOpo2-py3.10/lib/python3.10/site-packages/mkdocs_autorefs/references.py", line 191, in fix_refs
    html = AUTO_REF_RE.sub(fix_ref(url_mapper, unmapped), html)
  File "/home/sras/.cache/pypoetry/virtualenvs/docstring-thing-Gq5GOpo2-py3.10/lib/python3.10/site-packages/mkdocs_autorefs/references.py", line 157, in inner
    url = url_mapper(unescape(identifier))
  File "/home/sras/.cache/pypoetry/virtualenvs/docstring-thing-Gq5GOpo2-py3.10/lib/python3.10/site-packages/mkdocs_autorefs/plugin.py", line 107, in get_item_url
    url = self._get_item_url(identifier, fallback)
  File "/home/sras/.cache/pypoetry/virtualenvs/docstring-thing-Gq5GOpo2-py3.10/lib/python3.10/site-packages/mkdocs_autorefs/plugin.py", line 83, in _get_item_url
    new_identifiers = fallback(identifier)
  File "/home/sras/.cache/pypoetry/virtualenvs/docstring-thing-Gq5GOpo2-py3.10/lib/python3.10/site-packages/mkdocstrings/handlers/base.py", line 531, in get_anchors
    anchors = handler.get_anchors(handler.collect(identifier, fallback_config))
  File "/home/sras/.cache/pypoetry/virtualenvs/docstring-thing-Gq5GOpo2-py3.10/lib/python3.10/site-packages/mkdocstrings_handlers/python/handler.py", line 223, in collect
    doc_object = self._modules_collection[identifier]
  File "/home/sras/.cache/pypoetry/virtualenvs/docstring-thing-Gq5GOpo2-py3.10/lib/python3.10/site-packages/griffe/mixins.py", line 28, in __getitem__
    return self.members[parts[0]][parts[1:]]  # type: ignore[attr-defined]
  File "/home/sras/.cache/pypoetry/virtualenvs/docstring-thing-Gq5GOpo2-py3.10/lib/python3.10/site-packages/griffe/mixins.py", line 28, in __getitem__
    return self.members[parts[0]][parts[1:]]  # type: ignore[attr-defined]
  File "/home/sras/.cache/pypoetry/virtualenvs/docstring-thing-Gq5GOpo2-py3.10/lib/python3.10/site-packages/griffe/mixins.py", line 28, in __getitem__
    return self.members[parts[0]][parts[1:]]  # type: ignore[attr-defined]
  File "/home/sras/.cache/pypoetry/virtualenvs/docstring-thing-Gq5GOpo2-py3.10/lib/python3.10/site-packages/griffe/dataclasses.py", line 817, in __getitem__
    return self.target[key]
  File "/home/sras/.cache/pypoetry/virtualenvs/docstring-thing-Gq5GOpo2-py3.10/lib/python3.10/site-packages/griffe/dataclasses.py", line 1078, in target
    self.resolve_target()
  File "/home/sras/.cache/pypoetry/virtualenvs/docstring-thing-Gq5GOpo2-py3.10/lib/python3.10/site-packages/griffe/dataclasses.py", line 1105, in resolve_target
    self._resolve_target()
  File "/home/sras/.cache/pypoetry/virtualenvs/docstring-thing-Gq5GOpo2-py3.10/lib/python3.10/site-packages/griffe/dataclasses.py", line 1113, in _resolve_target
    raise AliasResolutionError(self.target_path) from error
griffe.exceptions.AliasResolutionError: Could not resolve polars

Expected behavior
I would want it not to break. Linking to the actual library class is not needed.
Screenshots

System (please complete the following information):

  • mkdocstrings-python version: 0.20
  • Python version: 3.10
  • OS: Ubuntu 22.04.1 LTS (in WSL)

Additional context
I'm reexporting it because I need to register extra functions. I'm using a linter to force all polars imports to go through that file to be sure that the functions are registered.

Add support for globs in paths configuration

Is your feature request related to a problem? Please describe.
We are using mkdocs in a monorepo. In this monorepo, we have many packages and a top level mkdocs configuration. We currently need to list every one of our package paths individually in the paths configuration option. However, the paths to all the modules in our monorepo could be easily described with a couple globs (ex: lib/*/module).

Describe the solution you'd like
It would be great if the paths configuration option supported a glob syntax.

Describe alternatives you've considered
We've thought about making our mkdocs.yml a generated file, but this is a bit cumbersome.

Additional context
I could see this being done either in this package by resolving the globs before passing them to the griffe loader or as a native feature of griffe itself. Based on the code though, it seems like it would be simplest to add directly in this package.

Support for markdown tables inside docstrings

Is your feature request related to a problem? Please describe.

I can't get this markdown table to render properly when it's part of a function docstring:

    +------------+-----------------+------------+------------------+
    | a          | [b=Table2.rows] | {c=Table3} | [d]              |
    +============+=================+============+==================+
    | 1          | foo             | cols.bar   | Table4.rows.baz  |
    +------------+-----------------+------------+------------------+
    | 2          | moo             | rows.oink  | Table5.cols.bork |
    +------------+-----------------+------------+------------------+

It renders like this:

image

Describe the solution you'd like

Support for the tables markdown extension, even when the table is inside a docstring.

Describe alternatives you've considered

  • Not using a table in the docstring. Meh.

Additional context

mkdocs.yml:

site_name: foo
docs_dir: src
site_dir: dist
theme: material

markdown_extensions:
  - def_list
  - tables
  - toc:
      permalink: true

plugins:
  - search

  - gen-files:
      scripts:
        - gen_pages.py

  - mkdocstrings:
      handlers:
        python:
          import:
            - https://docs.python.org/3/objects.inv
          paths: [../..]
          options:
            docstring_style: google
            show_if_no_docstring: True
            filters: []

  - literate-nav:
      nav_file: nav.md

requirements.txt:

mkdocs~=1.3
mkdocstrings[python]>=0.18
mkdocs-material~=8.4
mkdocs-gen-files~=0.3.5
mkdocs-literate-nav~=0.4.1

Option to include parameters that aren't in the docstring

Is your feature request related to a problem? Please describe.
Where I work, we try to avoid redundant docstrings, i.e. parameter names are as self-explanatory as possible, and they are type-annotated. However, those parameters then don't appear in mkdocstrings' rendered table/list/spacy of parameters.

Describe the solution you'd like
An option to show all parameters of a function, even if some parameters aren't explicitly mentioned in the docstring. Likewise for the return type, if it is specified in the code.

!include directive fails

In short: I have a repo that includes another one.

  - multirepo:
      cleanup: false
      temp_dir: multirepo_imports
      repos:
        - section: 'MedUX common'
          import_url: 'https://gitlab.com/nerdocs/medux/medux-common?branch=development'

This works, but I can't do the navigation of my main repo myself, as nav is treated with higher priority as the multirepo repos directive.
So I tried the other way:

nav:
   - Medux common: "!include https://gitlab.com/nerdocs/medux/medux-common?branch=development"

But I only get a

WARNING  -  [13:28:50] "GET /!include%20https:/gitlab.com/nerdocs/medux/medux-common?branch=development

Expected behavior
I suppose the !include directive should work this way.

System (please complete the following information):

  • mkdocstrings 0.19.0
  • mkdocstrings-python 0.8.2
  • Python version: 3.10
  • OS: Linux

Don't render star in signature before keyword-only params if signature has variadic positional param

Describe the bug
See machow/quartodoc#117.

Quote:

What we could improve here (in quartodoc and mkdocstrings) is that in case of both variadic positional and keyword-only parameters, we shouldn't add a single star to the signature, as doing so in the code raises a SyntaxError and therefore is not possible:

def f(a, *b, *, c): ...
             ^
SyntaxError: * argument may appear only once

Expected behavior
No star in signature when it has both varpos and kwonly parameters.

Page completely blank

Describe the bug
I'm trying to create a documentation page and the page is blank.

To Reproduce
Steps to reproduce the behavior:

  1. Clone my repository
  2. mkdocs serve
  3. Go to the API documentation page

Expected behavior
I expect to see my classes and functions appear on the page

Screenshots
image

System (please complete the following information):

  • mkdocstrings-python version: 0.7.1
  • Python version: 3.10.5
  • OS: Raspberry Pi OS

Additional context

`mkdocs serve -v` output
(.venv) pi@pi:/mnt/ssd/pynoonlight $ mkdocs -v serve
INFO     -  Building documentation...
DEBUG    -  Loading configuration file: /mnt/ssd/pynoonlight/mkdocs.yml
DEBUG    -  Loaded theme configuration for 'material' from '/mnt/ssd/pynoonlight/.venv/lib/python3.10/site-packages/material/mkdocs_theme.yml': {'language':
         'en', 'direction': None, 'features': [], 'palette': {'primary': None, 'accent': None}, 'font': {'text': 'Roboto', 'code': 'Roboto Mono'}, 'icon':
         None, 'favicon': 'assets/images/favicon.png', 'include_search_page': False, 'search_index_only': True, 'static_templates': ['404.html']}
DEBUG    -  Config value: 'config_file_path' = '/mnt/ssd/pynoonlight/mkdocs.yml'
DEBUG    -  Config value: 'site_name' = 'pynoonlight'
DEBUG    -  Config value: 'nav' = [{'Introduction': 'index.md'}, 'api_docs.md', 'changelog.md']
DEBUG    -  Config value: 'pages' = None
DEBUG    -  Config value: 'site_url' = ''
DEBUG    -  Config value: 'site_description' = None
DEBUG    -  Config value: 'site_author' = None
DEBUG    -  Config value: 'theme' = Theme(name='material', dirs=['/mnt/ssd/pynoonlight/.venv/lib/python3.10/site-packages/material',
         '/mnt/ssd/pynoonlight/.venv/lib/python3.10/site-packages/mkdocs/templates'], static_templates=['404.html', 'sitemap.xml'],
         locale=Locale(language='en', territory=''), language='en', direction=None, features=[], palette=[{'scheme': 'default', 'toggle': {'icon':
         'material/toggle-switch-off-outline', 'name': 'Switch to dark mode'}}, {'scheme': 'slate', 'toggle': {'icon': 'material/toggle-switch', 'name':
         'Switch to light mode'}}], font={'text': 'Roboto', 'code': 'Roboto Mono'}, icon=None, favicon='assets/images/favicon.png',
         include_search_page=False, search_index_only=True)
DEBUG    -  Config value: 'docs_dir' = '/mnt/ssd/pynoonlight/docs'
DEBUG    -  Config value: 'site_dir' = '/tmp/mkdocs_1tmuo7fw'
DEBUG    -  Config value: 'copyright' = None
DEBUG    -  Config value: 'google_analytics' = None
DEBUG    -  Config value: 'dev_addr' = Address(host='127.0.0.1', port=8000)
DEBUG    -  Config value: 'use_directory_urls' = True
DEBUG    -  Config value: 'repo_url' = 'https://github.com/IceBotYT/pynoonlight'
DEBUG    -  Config value: 'repo_name' = 'GitHub'
DEBUG    -  Config value: 'edit_uri' = 'edit/master/docs/'
DEBUG    -  Config value: 'extra_css' = []
DEBUG    -  Config value: 'extra_javascript' = []
DEBUG    -  Config value: 'extra_templates' = []
DEBUG    -  Config value: 'markdown_extensions' = ['toc', 'tables', 'fenced_code', 'pymdownx.snippets']
DEBUG    -  Config value: 'mdx_configs' = {'pymdownx.snippets': {'check_paths': True}}
DEBUG    -  Config value: 'strict' = False
DEBUG    -  Config value: 'remote_branch' = 'gh-pages'
DEBUG    -  Config value: 'remote_name' = 'origin'
DEBUG    -  Config value: 'extra' = {}
DEBUG    -  Config value: 'plugins' = PluginCollection([('search', <material.plugins.search.plugin.SearchPlugin object at 0xb58f9460>), ('mkdocstrings',
         <mkdocstrings.plugin.MkdocstringsPlugin object at 0xb58af550>)])
DEBUG    -  Config value: 'watch' = ['/mnt/ssd/pynoonlight/src/pynoonlight']
DEBUG    -  mkdocstrings: Adding extension to the list
DEBUG    -  mkdocstrings: Added a subdued autorefs instance <mkdocs_autorefs.plugin.AutorefsPlugin object at 0xb5885808>
DEBUG    -  mkdocs_autorefs.plugin: Adding AutorefsExtension to the list
INFO     -  Cleaning site directory
DEBUG    -  Reading markdown pages.
DEBUG    -  Reading: index.md
DEBUG    -  Reading: api_docs.md
DEBUG    -  mkdocstrings: Matched '::: pynoonlight'
DEBUG    -  mkdocstrings: Using handler 'python'
DEBUG    -  mkdocstrings: Collecting data
DEBUG    -  griffe: Found pynoonlight: loading
DEBUG    -  griffe: Loading path /mnt/ssd/pynoonlight/src/pynoonlight/__init__.py
DEBUG    -  griffe: Loading path /mnt/ssd/pynoonlight/src/pynoonlight/dispatch.py
DEBUG    -  griffe: Iteration 1 finished, 0 aliases resolved, still 0 to go
DEBUG    -  mkdocstrings: Updating renderer's env
DEBUG    -  mkdocstrings: Rendering templates
DEBUG    -  mkdocstrings: python/templates/material/module.html: Rendering pynoonlight
DEBUG    -  mkdocstrings: python/templates/material/children.html: Rendering children of pynoonlight
DEBUG    -  mkdocstrings: python/templates/material/children.html: <Module(PosixPath('/mnt/ssd/pynoonlight/src/pynoonlight/__init__.py'))>
DEBUG    -  Reading: changelog.md
DEBUG    -  mkdocstrings: Creating inventory file objects.inv
DEBUG    -  Copying static assets.
DEBUG    -  Copying media file: 'assets/images/favicon.png'
DEBUG    -  Copying media file: 'assets/javascripts/bundle.9c69f0bc.min.js'
DEBUG    -  Copying media file: 'assets/javascripts/bundle.9c69f0bc.min.js.map'
DEBUG    -  Copying media file: 'assets/javascripts/lunr/min/lunr.ar.min.js'
DEBUG    -  Copying media file: 'assets/javascripts/lunr/min/lunr.da.min.js'
DEBUG    -  Copying media file: 'assets/javascripts/lunr/min/lunr.de.min.js'
DEBUG    -  Copying media file: 'assets/javascripts/lunr/min/lunr.du.min.js'
DEBUG    -  Copying media file: 'assets/javascripts/lunr/min/lunr.es.min.js'
DEBUG    -  Copying media file: 'assets/javascripts/lunr/min/lunr.fi.min.js'
DEBUG    -  Copying media file: 'assets/javascripts/lunr/min/lunr.fr.min.js'
DEBUG    -  Copying media file: 'assets/javascripts/lunr/min/lunr.hi.min.js'
DEBUG    -  Copying media file: 'assets/javascripts/lunr/min/lunr.hu.min.js'
DEBUG    -  Copying media file: 'assets/javascripts/lunr/min/lunr.it.min.js'
DEBUG    -  Copying media file: 'assets/javascripts/lunr/min/lunr.ja.min.js'
DEBUG    -  Copying media file: 'assets/javascripts/lunr/min/lunr.jp.min.js'
DEBUG    -  Copying media file: 'assets/javascripts/lunr/min/lunr.multi.min.js'
DEBUG    -  Copying media file: 'assets/javascripts/lunr/min/lunr.nl.min.js'
DEBUG    -  Copying media file: 'assets/javascripts/lunr/min/lunr.no.min.js'
DEBUG    -  Copying media file: 'assets/javascripts/lunr/min/lunr.pt.min.js'
DEBUG    -  Copying media file: 'assets/javascripts/lunr/min/lunr.ro.min.js'
DEBUG    -  Copying media file: 'assets/javascripts/lunr/min/lunr.ru.min.js'
DEBUG    -  Copying media file: 'assets/javascripts/lunr/min/lunr.stemmer.support.min.js'
DEBUG    -  Copying media file: 'assets/javascripts/lunr/min/lunr.sv.min.js'
DEBUG    -  Copying media file: 'assets/javascripts/lunr/min/lunr.th.min.js'
DEBUG    -  Copying media file: 'assets/javascripts/lunr/min/lunr.tr.min.js'
DEBUG    -  Copying media file: 'assets/javascripts/lunr/min/lunr.vi.min.js'
DEBUG    -  Copying media file: 'assets/javascripts/lunr/min/lunr.zh.min.js'
DEBUG    -  Copying media file: 'assets/javascripts/lunr/tinyseg.js'
DEBUG    -  Copying media file: 'assets/javascripts/lunr/wordcut.js'
DEBUG    -  Copying media file: 'assets/javascripts/workers/search.ecf98df9.min.js'
DEBUG    -  Copying media file: 'assets/javascripts/workers/search.ecf98df9.min.js.map'
DEBUG    -  Copying media file: 'assets/stylesheets/main.69437709.min.css'
DEBUG    -  Copying media file: 'assets/stylesheets/main.69437709.min.css.map'
DEBUG    -  Copying media file: 'assets/stylesheets/palette.cbb835fc.min.css'
DEBUG    -  Copying media file: 'assets/stylesheets/palette.cbb835fc.min.css.map'
DEBUG    -  Building theme template: 404.html
DEBUG    -  Building theme template: sitemap.xml
DEBUG    -  Gzipping template: sitemap.xml
DEBUG    -  Building markdown pages.
DEBUG    -  Building page index.md
DEBUG    -  mkdocs_autorefs.plugin: Fixing references in page index.md
DEBUG    -  Building page api_docs.md
DEBUG    -  mkdocs_autorefs.plugin: Fixing references in page api_docs.md
DEBUG    -  Building page changelog.md
DEBUG    -  mkdocs_autorefs.plugin: Fixing references in page changelog.md
DEBUG    -  mkdocstrings: Tearing handlers down
INFO     -  Documentation built in 1.12 seconds
DEBUG    -  [19:21:05] Watching '/mnt/ssd/pynoonlight/docs'
DEBUG    -  [19:21:05] Watching '/mnt/ssd/pynoonlight/mkdocs.yml'
DEBUG    -  [19:21:05] Watching '/mnt/ssd/pynoonlight/src/pynoonlight'
INFO     -  [19:21:05] Watching paths for changes: 'docs', 'mkdocs.yml', 'src/pynoonlight'
INFO     -  [19:21:05] Serving on http://127.0.0.1:8000/
DEBUG    -  [19:21:09] "GET / HTTP/1.1" code 200
DEBUG    -  [19:21:09] "GET /assets/stylesheets/palette.cbb835fc.min.css HTTP/1.1" code 200
DEBUG    -  [19:21:09] "GET /assets/stylesheets/main.69437709.min.css HTTP/1.1" code 200
DEBUG    -  [19:21:09] "GET /assets/_mkdocstrings.css HTTP/1.1" code 200
DEBUG    -  [19:21:09] "GET /assets/javascripts/bundle.9c69f0bc.min.js HTTP/1.1" code 200
DEBUG    -  [19:21:09] "GET /search/search_index.json HTTP/1.1" code 200
INFO     -  [19:21:09] Browser connected: http://127.0.0.1:8000/
DEBUG    -  [19:21:09] "GET /assets/javascripts/workers/search.ecf98df9.min.js HTTP/1.1" code 200
DEBUG    -  [19:21:10] "GET /assets/images/favicon.png HTTP/1.1" code 200
DEBUG    -  [19:21:12] "GET /api_docs/ HTTP/1.1" code 200
DEBUG    -  [19:21:12] "GET /assets/_mkdocstrings.css HTTP/1.1" code 200
DEBUG    -  [19:21:12] "GET /assets/stylesheets/main.69437709.min.css HTTP/1.1" code 200
DEBUG    -  [19:21:12] "GET /assets/stylesheets/palette.cbb835fc.min.css HTTP/1.1" code 200
DEBUG    -  [19:21:12] "GET /assets/javascripts/bundle.9c69f0bc.min.js HTTP/1.1" code 200
DEBUG    -  [19:21:12] "GET /search/search_index.json HTTP/1.1" code 200
INFO     -  [19:21:12] Browser connected: http://127.0.0.1:8000/api_docs/
DEBUG    -  [19:21:12] "GET /assets/javascripts/workers/search.ecf98df9.min.js HTTP/1.1" code 200
DEBUG    -  [19:21:13] "GET /assets/images/favicon.png HTTP/1.1" code 200
^CINFO     -  Shutting down...

Interactive Python sessions in docstrings do not create code-blocks

Describe the bug

Interactive Python prompts (>>>) in docstrings are parsed as chevrons instead of creating code-blocks.

Expected behavior

The prompts should be detected so as to create interactive Python code-blocks. The legacy python handler does.

Screenshots

The following text in a docstring leads to an admonition with ill-formated code.

Example:
    >>> x = torch.rand(5, 3, 256, 256)
    >>> l = tv(x)
    >>> l.size()
    torch.Size([5])

image

System (please complete the following information):

  • mkdocstrings-python version: 0.6.6
  • Python version: 3.8.10
  • OS: Ubuntu 20.04

Additional context

This formatting is very common in Google-style and NumPy-style docstrings and allows to use doctest.

show_category_heading: true and group_by_category: true does not work

Describe the bug
Using show_category_heading: true and group_by_category: true does not work.

To Reproduce
Enable these settings

Expected behavior
Expected to have TOC separate them

Fix

The bug seems to happen here

{% if config.show_category_heading and obj.attributes.values()|any %}

Removing any() results in the expected behavior.

Since we're calling .values(), if there's no values it already returns False.

path does not working if cwd is not the cfg file location

Describe the bug
path does not working if cwd is not the cfg file location since path accepts glob

To Reproduce

  1. move the mkdocs.yml into a folder, for example tools/mkdocs
  2. run command mkdocs build -f ./tools/mkdocs/mkdocs.yml -d ../../site
  3. See error

Dataclasses syntax

Describe the bug

@dataclass
class Foo:
    bar: str
    """documentation for bar"""

Here bar is recognized by mkdocstring-python as a class-variable, it should parsed like arguments

Screenshots
image

While this is what I would expect:
image

Note that when implementing this any library that uses PEP 681 should treated the same

@property shows setter only

Describe the bug
I have a class which has a @property getter and @property.setter. It doesn't show up on the new experimental parser.

To Reproduce
Make a class with a property setter and getter

Expected behavior
Expected to have a property join getter and setter and tag it as writable, as the old parser did, or some other form of making clear that it's a writable property

Screenshots
Source:

class Resolve:

    @property
    def page(self) -> str:
        """Page Attribute

        Returns:
            str: Returns page name
        """
        return self._obj.GetCurrentPage()

    @page.setter
    def page(self, page: str) -> None:
        """Page Setter test

        Args:
            page (str): valid page

        Raises:
            ValueError: _description_

        Returns:
            None: None
        """        
        if page in self.pages:
            return self._obj.OpenPage(page)
        validpages = " ".join(map(str, self.pages))
        raise ValueError(
            f'"{page}" is not a valid page. Available pages are: {validpages}'
        )

Docs:

CleanShot 2022-04-14 at 00 40 32@2x

System (please complete the following information):

  • mkdocstrings-python version: [e.g. 0.6.6]
  • Python version: [e.g. 3.9]
  • OS: Mac OS Big Sur

perf: Directly include subtemplate using section kind instead of condition

#56 (comment)

I was thinking about getting rid of the condition on sections kind, and include the subtemplate directly since their names are equal to the section kinds. But maybe the include instruction costs more, so, would have to actually do some profiling.

{% if docstring_sections %}
  {{ log.debug("Rendering docstring") }}
  {% for section in docstring_sections %}
    {% if config.show_docstring_description and section.kind.value == "text" %}
      {{ section.value|convert_markdown(heading_level, html_id) }}
    {% else %}
      {% include "docstring/" ~ section.kind.value ~ ".html" with context %}
    {% endif %}
  {% endfor %}
{% endif %}

Each subtemplate would then check its config option config.show_docstring_attributes etc.

Documentation request - document how to override CSS elements

Looking here: https://mkdocstrings.github.io/python/customization/ it describes the CSS classes which are used with mkdocstrings-python. Unfortunelty some of us are coming into this cold and so it's much less obvious how to customise them. Despite giving example CSS rules for Material and ReadTheDocs, there's no hint of where to copy-paste this code to.

I understand the basic principle of CSS and HTML, but have no idea about the architecture that would allow me to add additional CSS files.

Would it be possible to document how to override CSS elements (on the page linked above) or otherwise cross link the relevant documentation (say on Mkdocs?). At minimum, it would be helpful if those code examples for themes could be completed with instructions on what to do with them.


I'm hitting this because I personally find the grey styled code headings very distracting. All features other than the background are fine, but the grey box is tripping my eye into missing that it's a heading.

Class docstrings are never displayed

Describe the bug

The class docstrings are never displayed.

Screenshots

With the following class

class SSIM(nn.Module):
    r"""Creates a criterion that measures the SSIM
    between an input and a target.

    Args:
        window_size: The size of the window.
        sigma: The standard deviation of the window.
        n_channels: The number of channels $C$.
        reduction: Specifies the reduction to apply to the output:
            `'none'` | `'mean'` | `'sum'`.
    """

    def __init__(
        self,
        window_size: int = 11,
        sigma: float = 1.5,
        n_channels: int = 3,
        reduction: str = 'mean',
        **kwargs,
    ):
        pass

I get

image

when merge_init_into_class is false and

image

when it is true.

System (please complete the following information):

  • mkdocstrings-python version: 0.6.6
  • Python version: 3.8.10
  • OS: Ubuntu 20.04
plugins:
  - mkdocstrings:
      default_handler: python
      handlers:
        python:
          selection:
            docstring_style: google
          rendering:
            docstring_section_style: list
            heading_level: 3
            members_order: source
            merge_init_into_class: true
            show_bases: false
            show_if_no_docstring: false
            show_root_full_path: true
            show_root_heading: true
            show_source: false
            show_submodules: false
      watch:
        - piqa

Additional context

If I understand correctly the following logic, a docstring is displayed only if merge_init_into_class=true and the __init__ function has a docstring, but it is never the one from the class itself.

{% if config.merge_init_into_class %}
{% if "__init__" in class.members and class.members["__init__"].has_docstring %}
{% with docstring_sections = class.members["__init__"].docstring.parsed %}
{% include "docstring.html" with context %}
{% endwith %}
{% endif %}
{% endif %}

I think that if merge_init_into_class=false or __init__ does not have a docstring, the docstring of the class should be displayed, if any. If merge_init_into_class=true and both __init__ and the class have a docstring, it is more complicated but IMO, the class docstring should have precedence.

Black fails if types are strings

Describe the bug

Strings seem to have html escaped before being passed to black.

To Reproduce
Steps to reproduce the behavior:

Add some code like

https://github.com/samuelcolvin/dirty-equals/blob/c690abbb32e5893d3bb2634e1345ab30a2f46791/dirty_equals/_dict.py#L39-L45

Where the return type is a string.

On build you'll get an error like:

  File "/Users/samuel/code/dirty-equals/env/lib/python3.10/site-packages/black/parsing.py", line 132, in lib2to3_parse
    raise exc from None
black.parsing.InvalidInput: Cannot parse: 1:162: def settings(self, *, strict: Optional[bool] = None, partial: Optional[bool] = None, ignore_values: Union[None, Container[Any], Callable[[Any], bool]] = None) -> &#39;IsDict&#39;: pass

System (please complete the following information):

  • Python version: 3.10
  • OS: Linux/macos

docs requirements:

black==21.12b0
mkdocs==1.2.3
mkdocs-material==8.2.1
mkdocstrings[python]==0.18

Conda wrong dependencies

Describe the bug
When installing one of the following packages:

  • mkdocstrings
  • mkdocstrings-python
  • mkdocstrings-python-legacy
    All of those packages were installed (due to a wrong dependency definition I guess...)
    This behavior does not allow working with the legacy version...

To Reproduce
conda install mkdocstrings-python-legacy

System (please complete the following information):

  • mkdocstrings-python-legacy: 0.2.2
  • Python version: 3.7
  • OS: Linux

Positional-only arguments are mishandled in signatures

Describe the bug
Positional-only arguments are mishandled in signatures with / always being put at the start of a signature with positional-only arguments regardless of how many arguments are positional only.

To Reproduce
With the following test code being targeted by mkdocstrings

# test.py
def bar(foo: str, baz: int, /, *, bar: int = 123) -> None:
    """meow"""

and the following mkdocs.yml

# mkdocs.yml
site_name: "Docs"
plugins:
  - search
  - mkdocstrings:
      default_handler: python
      watch:
        - test.py

build documentation from this module and watch it place / at the start of bar's signature as shown in the following screenshot.

Expected behavior
/ should appear after baz in the signature.

Screenshots

image

System (please complete the following information):

  • mkdocstrings-python version: 0.7.0
  • mkdocstrings version: 0.19.0
  • griffe version: 0.20.0
  • mkdocs version: 1.3.0
  • Python version: 3.10
  • OS: Windows

Additional context
This leads to an error being raised in cases where black is used to reformat function signatures with positional only arguments as / cannot be the first argument of a function syntax wise.

I can't really read this code but from what I can tell the responsible code might be here

{%- if parameter.kind.value == "positional-only" -%}
{%- if ns.render_pos_only_separator -%}
{%- set ns.render_pos_only_separator = False %}/, {% endif -%}
(where it's adding in / the moment it finds a positional only argument that isn't named self or cls rather than waiting until it reaches the end of the positional only arguments). I did try griffe with the example code and it seemed to be handling positional-only arguments properly.

Module not found

Hello,
I have problems in generating documentation from python module. It says that module was not found for importing.
However I am not sure where to search further.

python 3.9.12
mkdocs=1.4.2
mkdocstrings=0.19.1
mkdocstrings-python=0.8.3

Can anyone point me in the right direction here?

ERROR - Error reading page 'libs/iot/azure/azure_device_client.md': Empty module name
Traceback (most recent call last):
File "C:\Users\deguenth\AppData\Local\pypoetry\Cache\virtualenvs\taf-qmYDp-KU-py3.9\lib\site-packages\griffe\loader.py", line 139, in load_module
module_name, package = self.finder.find_spec(module, try_relative_path)
File "C:\Users\deguenth\AppData\Local\pypoetry\Cache\virtualenvs\taf-qmYDp-KU-py3.9\lib\site-packages\griffe\finder.py", line 119, in find_spec
return module_name, self.find_package(top_module_name)
File "C:\Users\deguenth\AppData\Local\pypoetry\Cache\virtualenvs\taf-qmYDp-KU-py3.9\lib\site-packages\griffe\finder.py", line 159, in find_package
raise ModuleNotFoundError(module_name)
ModuleNotFoundError

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
File "C:\Program Files\Python39\lib\runpy.py", line 197, in _run_module_as_main
return _run_code(code, main_globals, None,
File "C:\Program Files\Python39\lib\runpy.py", line 87, in run_code
exec(code, run_globals)
File "C:\Users\deguenth\AppData\Local\pypoetry\Cache\virtualenvs\taf-qmYDp-KU-py3.9\Scripts\mkdocs.exe_main
.py", line 7, in
File "C:\Users\deguenth\AppData\Local\pypoetry\Cache\virtualenvs\taf-qmYDp-KU-py3.9\lib\site-packages\click\core.py", line 1130, in call
return self.main(*args, **kwargs)
File "C:\Users\deguenth\AppData\Local\pypoetry\Cache\virtualenvs\taf-qmYDp-KU-py3.9\lib\site-packages\click\core.py", line 1055, in main
rv = self.invoke(ctx)
File "C:\Users\deguenth\AppData\Local\pypoetry\Cache\virtualenvs\taf-qmYDp-KU-py3.9\lib\site-packages\click\core.py", line 1657, in invoke
return _process_result(sub_ctx.command.invoke(sub_ctx))
File "C:\Users\deguenth\AppData\Local\pypoetry\Cache\virtualenvs\taf-qmYDp-KU-py3.9\lib\site-packages\click\core.py", line 1404, in invoke
return ctx.invoke(self.callback, **ctx.params)
File "C:\Users\deguenth\AppData\Local\pypoetry\Cache\virtualenvs\taf-qmYDp-KU-py3.9\lib\site-packages\click\core.py", line 760, in invoke
return _callback(*args, **kwargs)
File "C:\Users\deguenth\AppData\Local\pypoetry\Cache\virtualenvs\taf-qmYDp-KU-py3.9\lib\site-packages\mkdocs_main
.py", line 234, in serve_command
serve.serve(dev_addr=dev_addr, livereload=livereload, watch=watch, **kwargs)
File "C:\Users\deguenth\AppData\Local\pypoetry\Cache\virtualenvs\taf-qmYDp-KU-py3.9\lib\site-packages\mkdocs\commands\serve.py", line 83, in serve
builder(config)
File "C:\Users\deguenth\AppData\Local\pypoetry\Cache\virtualenvs\taf-qmYDp-KU-py3.9\lib\site-packages\mkdocs\commands\serve.py", line 76, in builder
build(config, live_server=live_server, dirty=dirty)
File "C:\Users\deguenth\AppData\Local\pypoetry\Cache\virtualenvs\taf-qmYDp-KU-py3.9\lib\site-packages\mkdocs\commands\build.py", line 308, in build
_populate_page(file.page, config, files, dirty)
File "C:\Users\deguenth\AppData\Local\pypoetry\Cache\virtualenvs\taf-qmYDp-KU-py3.9\lib\site-packages\mkdocs\commands\build.py", line 181, in _populate_page
page.render(config, files)
File "C:\Users\deguenth\AppData\Local\pypoetry\Cache\virtualenvs\taf-qmYDp-KU-py3.9\lib\site-packages\mkdocs\structure\pages.py", line 270, in render
self.content = md.convert(self.markdown)
File "C:\Users\deguenth\AppData\Local\pypoetry\Cache\virtualenvs\taf-qmYDp-KU-py3.9\lib\site-packages\markdown\core.py", line 264, in convert
root = self.parser.parseDocument(self.lines).getroot()
File "C:\Users\deguenth\AppData\Local\pypoetry\Cache\virtualenvs\taf-qmYDp-KU-py3.9\lib\site-packages\markdown\blockparser.py", line 90, in parseDocument
self.parseChunk(self.root, '\n'.join(lines))
File "C:\Users\deguenth\AppData\Local\pypoetry\Cache\virtualenvs\taf-qmYDp-KU-py3.9\lib\site-packages\markdown\blockparser.py", line 105, in parseChunk
self.parseBlocks(parent, text.split('\n\n'))
File "C:\Users\deguenth\AppData\Local\pypoetry\Cache\virtualenvs\taf-qmYDp-KU-py3.9\lib\site-packages\markdown\blockparser.py", line 123, in parseBlocks
if processor.run(parent, blocks) is not False:
File "C:\Users\deguenth\AppData\Local\pypoetry\Cache\virtualenvs\taf-qmYDp-KU-py3.9\lib\site-packages\mkdocstrings\extension.py", line 121, in run
html, handler, data = self._process_block(identifier, block, heading_level)
File "C:\Users\deguenth\AppData\Local\pypoetry\Cache\virtualenvs\taf-qmYDp-KU-py3.9\lib\site-packages\mkdocstrings\extension.py", line 193, in _process_block
data: CollectorItem = handler.collect(identifier, options)
File "C:\Users\deguenth\AppData\Local\pypoetry\Cache\virtualenvs\taf-qmYDp-KU-py3.9\lib\site-packages\mkdocstrings_handlers\python\handler.py", line 213, in collect
loader.load_module(module_name)
File "C:\Users\deguenth\AppData\Local\pypoetry\Cache\virtualenvs\taf-qmYDp-KU-py3.9\lib\site-packages\griffe\loader.py", line 145, in load_module
top_module = self._inspect_module(module) # type: ignore[arg-type]
File "C:\Users\deguenth\AppData\Local\pypoetry\Cache\virtualenvs\taf-qmYDp-KU-py3.9\lib\site-packages\griffe\loader.py", line 504, in inspect_module
module = inspect(
File "C:\Users\deguenth\AppData\Local\pypoetry\Cache\virtualenvs\taf-qmYDp-KU-py3.9\lib\site-packages\griffe\agents\inspector.py", line 88, in inspect
return Inspector(
File "C:\Users\deguenth\AppData\Local\pypoetry\Cache\virtualenvs\taf-qmYDp-KU-py3.9\lib\site-packages\griffe\agents\inspector.py", line 218, in get_module
value = dynamic_import(import_path, import_paths)
File "C:\Users\deguenth\AppData\Local\pypoetry\Cache\virtualenvs\taf-qmYDp-KU-py3.9\lib\site-packages\griffe\importer.py", line 59, in dynamic_import
module = import_module(module_path)
File "C:\Program Files\Python39\lib\importlib_init
.py", line 127, in import_module
return _bootstrap._gcd_import(name[level:], package, level)
File "", line 1027, in _gcd_import
File "", line 961, in _sanity_check
ValueError: Empty module name

The navigation path must not be empty

Describe the bug
When autogenerating Navigation I am getting following error:

raise ValueError(f"The navigation path must not be empty (got {keys!r})")
ValueError: The navigation path must not be empty (got ())

To Reproduce
Steps to reproduce the behavior:

import mkdocs_gen_files
nav = mkdocs_gen_files.Nav()

Expected behavior
It should not throw this exception as per example provided.

Screenshots
If applicable, add screenshots to help explain your problem.

System (please complete the following information):

  • mkdocstrings = { version = ">=0.20.0", extras = ["python"] }
  • Python version: 3.9
  • OS: [Windows]

Additional context
cur = self._data
if not keys:
raise ValueError(f"The navigation path must not be empty (got {keys!r})")

Exception: 'DocstringReturn' object is not iterable

Describe the bug
I attempted to use the new docstring handler for Python. The first time I tried to generate the documentation I encountered an unhanded exception.

The end of the stack trace:

...
   File "/opt/hostedtoolcache/Python/3.10.2/x64/lib/python3.10/site-packages/mkdocstrings_handlers/python/templates/material/_base/docstring.html", line 21, in top-level template code
    {% include "docstring/returns.html" with context %}
  File "/opt/hostedtoolcache/Python/3.10.2/x64/lib/python3.10/site-packages/mkdocstrings_handlers/python/templates/material/docstring/returns.html", line 1, in top-level template code
    {% extends "_base/docstring/returns.html" %}
  File "/opt/hostedtoolcache/Python/3.10.2/x64/lib/python3.10/site-packages/mkdocstrings_handlers/python/templates/material/_base/docstring/returns.html", line 3, in top-level template code
    {% set name_column = section.value|selectattr("name")|any %}
  File "/opt/hostedtoolcache/Python/3.10.2/x64/lib/python3.10/site-packages/mkdocstrings/handlers/base.py", line 57, in do_any
    return any(seq)
  File "/opt/hostedtoolcache/Python/3.10.2/x64/lib/python3.10/site-packages/jinja2/filters.py", line 1749, in select_or_reject
    for item in value:
TypeError: 'DocstringReturn' object is not iterable

To Reproduce
This failed CI step demonstrate the failure.

Expected behavior
The API documentation is generated as it did with the previous handler.

System (please complete the following information):

  • mkdocstrings-python version: 0.6.2
  • Python version: 3.10.2
  • OS: Ubuntu 20.04.3

An option to control whether the admonitions in python docstring should be collapsed

Is your feature request related to a problem? Please describe.
When I use admonitions in python docstring like this:

"""
Note:
    Details ...
"""

I noticed that an collapsed admonitions is rendered in the browser now.

I can use !!! note to make a uncollapsed admonition, but this will make the docstring strange for human reading.

Describe the solution you'd like
The information contained in 'Note' or 'Tips' or other admonitions are usually important information, and we don't want our users to miss them, so I think at least we have a choise to choose whether it should be collapsed.


Platform: Windows 10
mkdocstrings == 0.19.0
mkdocstrings-python == 0.7.0
griffe == 0.20.0

I don't know if I described the situation clearly 😂

Don't show the implicit `self` parameter in the function signature

Is your feature request related to a problem? Please describe.

I would like to not show the implicit self parameter in the function signatures. Since the documentation is most often read by a user of the object there is no need to show them to the explicit self parameter. The built in python help() docstring renderer does not show it.

Describe the solution you'd like

A config option to disable show self would be ideal. Defaulting to "dont show self" would be even better.

Describe alternatives you've considered

An alternative is to not have a config option and just never show it.

Relative cross-references

Limitations of absolute cross references

By default, mkdocstrings only supports cross-references where the path is
fully qualified or is empty, in which case it is taken from the title. But many times
you do not want to use fully qualified names everywhere in your doc strings, so you
must use the shorter name in the title and the full name in the path.

If you work with long package and class names or with namespace packages, this can result in a lot
of extra typing, harder to read doc-strings and more typographical errors.

For instance, here is a small example of what you need to do currently:

class MyClass:
    def this_method(self):
        """
        See [other_function][mypkg.mymod.MyClass.other_function] 
        from [MyClass][mypkg.mymod.Myclass]
        """

Relative cross-references

I propose that we support a relative_crossrefs option, that when enabled would instruct the python handler
to substitute relative path expressions into absolute paths based on the known path of the doc-string in
which it occurs along with the text in the title. For instance, the previous example could be written as:

class MyClass:
    def this_method(self):
        """
        See [other_function][.] from [MyClass][^]
        """

Relative path syntax

The relative path specifier has the following form:

  • If the path ends in . then the title text will be appended to the path
    (ignoring bold, italic or code markup).

  • If the path begins with . then it will be expanded relative to the path
    of the doc-string in which it occurs. As a special case, if the current
    doc-string is for a function or method, then . will instead be
    expanded relative to the function's parent (i.e. the same as ^.).

  • If the path begins with (c), that will be replaced by the path of the
    class that contains the doc-string

  • If the path begins with (m), that will be replaced by the path of the
    module that contains the doc-string

  • if the path begins with (p), that will be replaced by the path of the
    package that contains the doc-string. For this purpose, a package is
    a module that contains other modules or that does not have a parent
    module.

  • If the path begins with one or more ^ characters, then that will go
    up one level in the path of the current doc string for each ^

Examples

Using relative syntax

class MyClass:
    def this_method(self):
        """
        [`that_method`][.]
        [init method][(c).__init__]
        [this module][(m)]
        [OtherClass][(m).]
        [some_func][^^.]
        """

Using absolute syntax

class MyClass:
    def this_method(self):
        """
        [`that_method`][mypkg.mymod.MyClass.that_method]
        [init method][mypkg.mymod.MyClass.__init__]
        [this module][mypkg.mymod]
        [OtherClass][mypkg.mymod.OtherClass]
        [some_func][mypkg.mymod.some_func]
        [
        
        """

Bases links aren't correct

Describe the bug

Thanks so much for mkdocstrings, I remembered this project from a conversation we had years ago. I'm now using it on a library I'm just writing docs for dirty-equals.

I've managed to set everything up the way I want it, except the "Bases" links are not working quite right.

This is because I have types declared in dirty_equals._numeric but recommended for import from dirty_equals. This is meaning that while heading ids are correct (e.g. dirty_equals.IsNumeric), bases is generating a link of #dirty_equals._numeric.IsNumeric.

To Reproduce
Steps to reproduce the behavior:

  1. PR showing the problem is samuelcolvin/dirty-equals#11
  2. docs preview is https://smokeshow.helpmanual.io/07072c0r385x5x6x3u2d/, try the first "Bases" link.

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

Screenshots
If applicable, add screenshots to help explain your problem.

System (please complete the following information):

  • Python version: 3.10
  • OS: Linux/macos

docs requirements:

black==21.12b0
mkdocs==1.2.3
mkdocs-material==8.2.1
mkdocstrings[python]==0.18

Any suggestions on a workaround or when a fix might be available would be wonderful.

When a class method overrides it's parent class method, and has no docstring, inherit from the parent class method

Is your feature request related to a problem? Please describe.
It's better to describe it with an example.

from abc import abstractmethod, ABC
class Base(ABC):
    @abstractmethod
    def some_method():
        """Docstring...
        Args:
             ......
        """

class Child(Base):
    def some_method():
        # no docstring, expected to inherit from the abstract class.
        do_some_work

In the old legacy python handler, when a method that overrides a method from a base class has no docstring, it will inherit doctring from the method of the base class. So I only have to write docstring in the abstract class for a single time.

But in the new python handler, it will not. So I have to copy the same docstring to many of the child classes...

Describe the solution you'd like
Try to inherit from parent class if a method has no docstring.

I think a even better solution is, when some keywords write to the docstring, it will inherit docstring from parent class method:

class Child(Base):
    def some_method():
        """See base class"""

This is what google has suggested in https://google.github.io/styleguide/pyguide.html#383-functions-and-methods :

A method that overrides a method from a base class may have a simple docstring sending the reader to its overridden method’s docstring, such as """See base class.""". The rationale is that there is no need to repeat in many places documentation that is already present in the base method’s docstring. However, if the overriding method’s behavior is substantially different from the overridden method, or details need to be provided (e.g., documenting additional side effects), a docstring with at least those differences is required on the overriding method.

Provide documentation of syntax and decision logic for filter

Hi,

I have been trying to get mkdocstrings to document only public methods in my class. This means filtering our anything that starts with two underscores, except constructors.

Was missing information about the syntax of the filters. Is what follows the optional exclamation mark a regular expression? That would mean that the default ["!^_[^_]"] would filter out anything with a single underscore. My understanding is that that would be "protected" members but not "private" ones.

What would also need documenting is the logic that is applied when interpreting a list of filters. It looks like later filters take precedence? I was able to get only public members and constructors documented using the following configuration. Is this how it is intended? (I know the first filter expression is somewhat crude.)

options:
  filters:
    - "!__"
    - "__init__"

Cheers, Alex

Automatic generation of markdown files for all modules from src

Is your feature request related to a problem? Please describe.
Hey, I would like to automatically generate markdown files for all modules in a directory, recursively.

Afaik, their content should be in the ::: my_library.my_module.my_class format.

For now, I believe I need to manually create them for each module. When the complexity of the project grows, it's becoming problematic and unreasonable to add a new file manually.

Describe the solution you'd like
Any solution that will automatically generate these files so that I can add them to a navbar in my mkdocs.yml.

ToC names overflow if they are too long

Describe the bug
Entries in the ToC can overflow if they are too long. This results in them being cut off.

To Reproduce
Give a class a long name and watch the ToC

Expected behavior
Either

  1. A scroll wheel appears
  2. The name is cut-off with dots -> CommunityContentRouteHttp...

Option 2 feels the best from a UX standpoint IMO.

Screenshots
image
image

System (please complete the following information):

  • mkdocstrings-python version: [0.7.1]
  • Python version: [3.10]
  • OS: [Windows]
  • Theme: material

Additional context
See here for a live example

Add annotation links in signature

Is your feature request related to a problem? Please describe.
I often write functions/classes/etc which (I hope) are self-describing enough to exist without a docstring, or which have a docstring that doesn't describe all of the parameters. In this case the only place the parameters are shown are in the signature but their annotations do not contain links (when the annotation exists somewhere else in the codebase).

Describe the solution you'd like
It would be nice if there were an option to auto-generate these links similarly to how they are handled in the "Parameters" section created from the docstring. For example in the following signature:

def foo(baz: other_module.Baz) -> str:

I would like if the generated html contained a link to other_module.Baz.

Describe alternatives you've considered
Another option could be to create/update the docstring to add parameters based on the signature, similarly to how auto-docstring generators work but in this case leaving the original code untouched. I implemented a quick hack for this in griffe but I think it would require more work to make it a usable feature.

Additional context
I made a proof-of-concept patch (see below) to the function and signature templates to include links in a similar way to the docstring template. If this feature seems useful I could try to complete in a pull request (maybe adding a flag to turn it on/off and applying it to more than just the function template). The current released version makes a signature like:

original

And with my patch it looks like (the blue text has two correctly generated links):

patched

diff --git a/src/mkdocstrings_handlers/python/templates/material/_base/function.html b/src/mkdocstrings_handlers/python/templates/material/_base/function.html
index b9b1696..cc1dacd 100644
--- a/src/mkdocstrings_handlers/python/templates/material/_base/function.html
+++ b/src/mkdocstrings_handlers/python/templates/material/_base/function.html
@@ -24,10 +24,10 @@
       {% if config.separate_signature %}
         <span class="doc doc-object-name doc-function-name">{% if show_full_path %}{{ function.path }}{% else %}{{ function.name }}{% endif %}</span>
       {% else %}
-        {% filter highlight(language="python", inline=True) %}
+        <span class="doc doc-object-name doc-function-name">
           {% if show_full_path %}{{ function.path }}{% else %}{{ function.name }}{% endif %}
           {% include "signature.html" with context %}
-        {% endfilter %}
+        </span>
       {% endif %}
 
       {% with labels = function.labels %}
diff --git a/src/mkdocstrings_handlers/python/templates/material/_base/signature.html b/src/mkdocstrings_handlers/python/templates/material/_base/signature.html
index bc24ea3..40b7b4b 100644
--- a/src/mkdocstrings_handlers/python/templates/material/_base/signature.html
+++ b/src/mkdocstrings_handlers/python/templates/material/_base/signature.html
@@ -24,11 +24,21 @@
           {%- endif -%}
 
           {%- if config.show_signature_annotations and parameter.annotation is not none -%}
-            {%- set annotation = ": " + parameter.annotation|safe -%}
+            {%- set annotation -%}
+              {% with expression = parameter.annotation %}
+                {% include "expression.html" with context %}
+              {% endwith %}
+            {%- endset -%}
+            {%- set annotation = ": " + annotation -%}
           {%- endif -%}
 
           {%- if parameter.default is not none and parameter.kind.value != "variadic positional" and parameter.kind.value != "variadic keyword" -%}
-            {%- set default = ns.equal + parameter.default|safe -%}
+            {%- set default -%}
+              {% with expression = parameter.default %}
+                {% include "expression.html" with context %}
+              {% endwith %}
+            {%- endset -%}
+            {%- set default = ns.equal + default -%}
           {%- endif -%}
 
           {%- if parameter.kind.value == "variadic positional" -%}
@@ -42,7 +52,11 @@
         {%- endif -%}
       {%- endfor -%}
     )
-    {%- if config.show_signature_annotations and function.annotation %} -> {{ function.annotation|safe }}{%- endif -%}
+    {%- if config.show_signature_annotations and function.annotation %}
+      {% with expression = function.annotation %}
+        -> {% include "expression.html" with context %}
+      {% endwith %}
+    {%- endif -%}
 
   {%- endwith -%}
 {%- endif -%}
\ No newline at end of file

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.