Table of Contents
Based on the best understanding of the authors of pydoclint, here are some reasons (this may not be an exhaustive list):
inspect
module
in some places. (The inspect
module requires compiling the Python source
code, which can be time consuming for big code bases)pydoclint uses a static syntax analyzer (Python’s official AST module) to analyze the incoming Python source code.
The static syntax analysis is very fast because it doesn’t execute or evaluate any code. For example, this piece of Python code is not runnable:
a = b
because b
is not defined. But the static syntax analyzer does not “know”
this: it doesn’t need to “know” this to analyze the syntatic structure of
a = b
.
As a result, pydoclint is not designed to handle cases where Pythonic naming conventions are broken, such as:
classmethod
to something like hello
:hello = classmethod
class MyClass:
@hello
def myClassMethod(cls):
pass
staticmethod
to something else, similar to the classmethod
case
aboveself
or cls
in methods, such as:class MyClass:
def myMethod(hello, arg1): # the 1st argument is `self` by convention
pass
@classmethod
def myClassMethod(hey, arg2): # the 1st argument is `cls` by convention
pass
from typing import List as hello
from typing import Optional as world
def myFunc(arg1: hello[int], arg2: world[str]) -> None:
"""
An example function.
pydoclint expects consistency between signature type annotation (`hello[int]`)
and docstring type annotation (`List[int]`).
Parameters
----------
arg1 : List[int]
Arg 1
arg2 : world[str]
Arg 2
"""
print(arg1, arg2)
The authors of pydoclint feel that this is a sensible design choice to achieve and maintain pydoclint’s speed.
As mentioned in Section 2 above, pydoclint uses static syntax analysis. As a result, it cannot really “know” that these type annotations are in fact equivalent:
Type annotation | Equivalent version |
---|---|
Optional[str] |
str | None |
Union[str, int] |
int | str |
Tuple[str, int] |
tuple[str, int] |
Additionally, pydoclint does not recognize some docstring conventions allowed
in the docstring style guide, such as using “int, optional
” for
Optional[int]
.
Right now, the only way to make pydoclint stop reporting style violations is to make sure the docstring type annotations match the signature type annotations verbatim.
Again, the authors of pydoclint feel that this is a reasonable price to pay in order to achieve fast linting and reduce ambiguity.
The official Sphinx documentation does not explicitly state this, so it is unclear what header to use to specify the type of what a function yields.
Many people use rtype
, but the authors of pydoclint find it difficult to
differentiate the type of return value and the type of yield value.
Therefore, pydoclint expects the convention of ytype
for yield types. This
is actually common practice, as evident from a code search on GitHub:
https://github.com/search?q=%3Aytype%3A+language%3APython&type=code&l=Python
By default, pydoclint checks return type and yield type consistencies, and it also requires argument types in the docstring. In other words, by pydoclint’s default, this is an acceptable Google-style docstring:
"""
This is a function.
Args:
arg1 (int): Arg 1
arg2 (float): Arg 2
arg3 (Optional[Union[float, int, str]]): Arg 3
Returns:
int: Result
"""
However, this may not be the convention of a lot of Google-style docstring writers.
But do not worry: here are some config options to tweak:
--arg-type-hints-in-docstring
: you can set it to False
--check-return-types
: you can set it to False
--check-yield-types
: you can set it to False
Here are all the configurable options of pydoclint, and here is how to configure pydoclint.
If you have large legacy projects, adoting a new linter may be daunting: you’ll see hundreds or even thousands of violations at first.
Fortunately, pydoclint offers a “baseline” feature, which ignores existing violations for now, and will only report new violations.
To use this feature, you only need to generate a “baseline violations” file (containing the hundreds or thousands of existing violations) once, and save it somewhere in your repo.
For more details, please check out this section.
If you use Neovim, you can integrate pydoclint with your editor using the null-ls plugin. null-ls allows you to use linters and formatters in Neovim in a simple and efficient way. First, make sure you have installed null-ls using your preferred package manager. Next, add the following configuration to your Neovim config file to register pydoclint as a diagnostic source:
local null_ls = require("null-ls")
null_ls.setup({
sources = {
null_ls.builtins.diagnostics.pydoclint,
},
})
This will enable pydoclint to provide diagnostic messages for your Python code directly in Neovim. You can further customize the behavior of pydoclint by passing additional options:
local null_ls = require("null-ls")
null_ls.setup({
sources = {
null_ls.builtins.diagnostics.pydoclint.with({
extra_args = {"--style=google", "--check-return-types=False"},
}),
},
})
Adjust the extraargs based on your preferred _pydoclint configuration. With this setup, you can now enjoy the benefits of pydoclint’s fast and comprehensive docstring linting directly within your Neovim editing environment.