Numdoc Lint provides features such as NumPy style docstring code checking.
MIT License
Numdoc Lint provides features such as NumPy style docstring checking in Python code.
Descriptions of Python functions, modules, or classes written in the following format.
def sample_func(sample_arg_1, sample_arg_2=100, sample_arg_3='Apple'):
"""
Sample function description.
Parameters
----------
sample_arg_1 : int
First sample argument description.
sample_arg_2 : int, default 100
Second sample argument description.
sample_arg_3 : str, default 'Apple'
Third sample argument description.
Returns
----------
sample_return_value : int
Sample return value.
"""
return 100
For more details, please see A Guide to NumPy/SciPy Documentation.
Parameters
section mismatching.
Returns
section mismatching.$ pip install numdoclint
A single module will be checked with the check_python_module
function.
>>> import numdoclint
>>> lint_info_list = numdoclint.check_python_module(
... py_module_path='../pandas/pandas/core/arrays/array_.py')
Then Lint results will be displayed on standard output, as followed:
../pandas/pandas/core/arrays/array_.py::array
The function description is not set to docstring.
../pandas/pandas/core/arrays/array_.py::array
There is an argument whose explanation does not exist in docstring.
Target argument name: data
...
List of dicts will be returned, as followed:
>>> lint_info_list
[{'module_path': '../pandas/pandas/core/arrays/array_.py',
'func_name': 'array',
'info_id': 6,
'info': 'The function description is not set to docstring.'},
{'module_path': '../pandas/pandas/core/arrays/array_.py',
'func_name': 'array',
'info_id': 2,
'info': 'There is an argument whose explanation does not exist in docstring.\nTarget argument name: data'},
...
If execute check_python_module_recursively
function, then Numdoc Lint will check target directory recursively.
>>> import numdoclint
>>> lint_info_list = numdoclint.check_python_module_recursively(
... dir_path='../numpy/')
>>> import pandas as pd
>>> df = pd.DataFrame(data=lint_info_list)
>>> df.head(n=3)
>>> df[100:103]
If you only need lint result list, and not necessary standard output, then set verbose argument to 0 and stdout will be disabled.
>>> lint_info_list = numdoclint.check_python_module(
... py_module_path='../pandas/pandas/core/arrays/array_.py',
... verbose=0)
If you want to skip functions with a specific prefix, set prefix names to the skip_decorator_name_list
argument (default is [test_]
).
>>> lint_info_list = numdoclint.check_python_module(
... py_module_path='../pandas/pandas/core/arrays/array_.py',
... ignore_func_name_prefix_list=['test_', '_main', '__init__'])
You can specify IDs to ignore_info_id_list
argument to ignore.
The ID corresponds to the return value's info_id
.
# sample.py
def sample_func():
"""
Sample function.
Returns
-------
price : int
Sample price
"""
pass
>>> import numdoclint
>>> lint_info_list = numdoclint.check_python_module(
... py_module_path='./sample.py',
... verbose=0)
>>> lint_info_list
[{'module_path': './sample.py',
'func_name': 'sample_func',
'info_id': 12,
'info': 'While the return value document exists in docstring, the return value does not exist in the function.'}]
>>> lint_info_list = numdoclint.check_python_module(
... py_module_path='./sample.py',
... ignore_info_id_list=[12],
... verbose=0)
>>> lint_info_list
[]
Or you can also specify ID's constant to argument.
>>> lint_info_list = numdoclint.check_python_module(
... py_module_path='./sample.py',
... ignore_info_id_list=[
... numdoclint.INFO_ID_LACKED_RETURN_VAL,
... ],
... verbose=0)
>>> lint_info_list
[]
By default, the following docstring Parameters
default specification will not be checked.
def sample_func(price=100):
"""
Sample function.
Parameters
----------
price : int, default 100
Sample price.
"""
pass
If want to check default specification (e.g., , default 100
, , default is 100
, (default 100)
, or , optional
) strictly, then set enable_default_or_optional_doc_check
argument to True.
>>> lint_info_list = numdoclint.check_python_module(
... py_module_path='../pandas/pandas/core/frame.py',
... enable_default_or_optional_doc_check=True)
...
../pandas/pandas/core/frame.py::to_dict
While there is no description of default value in docstring, there is a default value on the argument side.
Argument name: orient
Argument default value: "dict"
...
By using the check_jupyter_notebook
and check_jupyter_notebook_recursively
interface, you can check Jupyter notebooks as well as Python modules.
check_result_list = numdoclint.check_jupyter_notebook(
notebook_path='./sample_notebook.ipynb')
check_result_list = numdoclint.check_jupyter_notebook_recursively(
dir_path='./sample_dir/')
ignore_func_name_prefix_list
, ignore_info_id_list
, and enable_default_or_optional_doc_check
arguments described above are also available.
You can run the check as well with the following command:
$ numdoclint -p ./sample/path.py
The following arguments are provided. Only --path
argument is required, other arguments are optional.
-h, --help show this help message and exit
-p PATH, --path PATH Python module file path, Jupyter notebook path, or
directory path.
-r, --check_recursively
If specified, check files recursively.In that case,
you need to specify the directory in the path
argument.
-j, --is_jupyter If specified, check target will become Jupyter
notebook. If not, Python module will be checked.
-f IGNORE_FUNC_NAME_PREFIX_LIST, --ignore_func_name_prefix_list IGNORE_FUNC_NAME_PREFIX_LIST
A prefix list of function name conditions to ignore.
e.g., 'test_,sample_'. Comma separated string is
acceptable.
-i IGNORE_INFO_ID_LIST, --ignore_info_id_list IGNORE_INFO_ID_LIST
List of IDs to ignore lint checking. e.g, '1,2,3'. Comma
separated integer is acceptable.
-o, --enable_default_or_optional_doc_check
If specified, the `default` and `optional` stringin
docstring will be checked.
-d SKIP_DECORATOR_NAME_LIST, --skip_decorator_name_list SKIP_DECORATOR_NAME_LIST
If a decorator name in this list is set to function,
that function will not be checked. Specify if
necessary for docstring-related decorators. Note: only
available when check Python module, not supported
Jupyter notebook.
$ numdoclint -p ./sample/dir/ -r
$ numdoclint -j -p ./sample/path.ipynb
$ numdoclint -j -r -p ./sample/dir/
# sample.py
def sample_func(price):
"""
Parameters
----------
name : str
Sample name.
"""
pass
>>> lint_info_list = numdoclint.check_python_module(
... py_module_path='./sample.py')
./sample.py::sample_func
The function description is not set to docstring.
# sample.py
def sample_func(price):
"""
Sample function.
Parameters
----------
price : int
Sample price.
lacked_arg : str
Sample string.
"""
pass
>>> lint_info_list = numdoclint.check_python_module(
... py_module_path='./sample.py')
./sample.py::sample_func
An argument exists in docstring does not exists in the actual argument.
Lacked argument name: lacked_arg
# sample.py
def sample_func(price, lacked_arg):
"""
Sample function.
Parameters
----------
price : int
Sample price.
"""
pass
>>> lint_info_list = numdoclint.check_python_module(
... py_module_path='./sample.py')
./sample.py::sample_func
There is an argument whose explanation does not exist in docstring.
Target argument name: lacked_arg
# sample.py
def sample_func(price):
"""
Sample function.
Parameters
----------
price
Sample price (type not specified).
"""
pass
>>> lint_info_list = numdoclint.check_python_module(
... py_module_path='./sample.py')
./sample.py::sample_func
Missing docstring argument type information.
Target argument: price
# sample.py
def sample_func(price, name):
"""
Sample function.
Parameters
----------
price : int
name : str
"""
pass
>>> lint_info_list = numdoclint.check_python_module(
... py_module_path='./sample.py')
./sample.py::sample_func
Missing docstring argument information.
Argument name: price
./sample.py::sample_func
Missing docstring argument information.
Argument name: name
# sample.py
def sample_func(price, name):
"""
Sample function.
Parameters
----------
name : str
Sample name.
price : int
Sample price.
"""
pass
>>> lint_info_list = numdoclint.check_python_module(
... py_module_path='./sample.py')
./sample.py::sample_func
The order of the argument and docstring is different.
Order of arguments: ['price', 'name']
Order of docstring parameters: ['name', 'price']
Note: Only enabled when enable_default_or_optional_doc_check=True
argument specified.
# sample.py
def sample_func(price=100):
"""
Sample function.
Parameters
----------
price : int
Sample price.
"""
pass
>>> lint_info_list = numdoclint.check_python_module(
... py_module_path='./sample.py',
... enable_default_or_optional_doc_check=True)
./sample.py::sample_func
While there is no description of default value in docstring, there is a default value on the argument side.
Argument name: price
Argument default value: 100
Good patterns:
, default xxx
specified (mainly used in Pandas):# sample.py
def sample_func(price=100):
"""
Sample function.
Parameters
----------
price : int, default 100
Sample price.
"""
pass
, default is xxx
specified (mainly used in NumPy):# sample.py
def sample_func(price=100):
"""
Sample function.
Parameters
----------
price : int, default is 100
Sample price.
"""
pass
(default 100)
specified (rarely used in Pands):# sample.py
def sample_func(price=100):
"""
Sample function.
Parameters
----------
price : int (default 100)
Sample price.
"""
pass
Note: Only enabled when enable_default_or_optional_doc_check=True
argument specified.
# sample.py
def sample_func(price):
"""
Sample function.
Parameters
----------
price : int, default 100
Sample price.
"""
pass
>>> lint_info_list = numdoclint.check_python_module(
... py_module_path='./sample.py',
... enable_default_or_optional_doc_check=True)
./sample.py::sample_func
The default value described in docstring does not exist in the actual argument.
Argment name: price
Docstring default value: 100
# sample.py
def sample_func():
"""
Sample function.
"""
return 100
>>> lint_info_list = numdoclint.check_python_module(
... py_module_path='./sample.py',
... enable_default_or_optional_doc_check=True)
./sample.py::sample_func
While the return value exists in the function, the return value document does not exist in docstring.
# sample.py
def sample_func():
"""
Sample function.
Returns
-------
price : int
"""
return 100
>>> lint_info_list = numdoclint.check_python_module(
... py_module_path='./sample.py')
./sample.py::sample_func
Docstring description of return value is missing.
Return value name: price
Return value type: int
Returns
docstring section exists# sample.py
def sample_func():
"""
Sample function.
Returns
-------
price : int
Sample price
"""
pass
>>> lint_info_list = numdoclint.check_python_module(
>>> py_module_path='./sample.py')
./sample.py::sample_func
While the return value document exists in docstring, the return value does not exist in the function.
The following library modules are used for testing and lint.
Command to run overall tests and lint:
$ python ./run_all_tests_and_lint.py
Command to run the entire test:
$ pytest --cov=numdoclint tests/ -v
Command to run the autoflake:
$ autoflake --in-place --remove-unused-variables --remove-all-unused-imports -r ./
Command to run the autopep8:
$ autopep8 --in-place --aggressive --aggressive --recursive ./
Command to run the isort:
$ isort -rc ./
Command to run the flake8:
$ flake8 ./
The following library are used for PyPI uploading.
Build command:
$ python build.py
Upload to TestPyPI:
$ twine upload --repository-url https://test.pypi.org/legacy/ dist/*
Install from TestPyPI:
$ pip install --index-url https://testpypi.python.org/simple/ numdoclint
Upload to PyPI:
$ twine upload dist/*