{"id":16461507,"url":"https://github.com/simon-ritchie/numdoclint","last_synced_at":"2025-07-23T12:35:02.421Z","repository":{"id":35009663,"uuid":"193196542","full_name":"simon-ritchie/numdoclint","owner":"simon-ritchie","description":"Numdoc Lint provides features such as NumPy style docstring code checking.","archived":false,"fork":false,"pushed_at":"2022-06-01T11:35:40.000Z","size":191,"stargazers_count":6,"open_issues_count":8,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-07-17T17:25:13.254Z","etag":null,"topics":["docstring","lint","numpy","pandas","python"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/simon-ritchie.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2019-06-22T05:45:45.000Z","updated_at":"2025-01-20T00:21:51.000Z","dependencies_parsed_at":"2022-08-08T03:16:22.708Z","dependency_job_id":null,"html_url":"https://github.com/simon-ritchie/numdoclint","commit_stats":null,"previous_names":[],"tags_count":17,"template":false,"template_full_name":null,"purl":"pkg:github/simon-ritchie/numdoclint","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/simon-ritchie%2Fnumdoclint","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/simon-ritchie%2Fnumdoclint/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/simon-ritchie%2Fnumdoclint/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/simon-ritchie%2Fnumdoclint/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/simon-ritchie","download_url":"https://codeload.github.com/simon-ritchie/numdoclint/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/simon-ritchie%2Fnumdoclint/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":266680320,"owners_count":23967791,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-07-23T02:00:09.312Z","response_time":66,"last_error":null,"robots_txt_status":null,"robots_txt_updated_at":null,"robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["docstring","lint","numpy","pandas","python"],"created_at":"2024-10-11T11:08:25.497Z","updated_at":"2025-07-23T12:35:02.399Z","avatar_url":"https://github.com/simon-ritchie.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Numdoc Lint\n\nNumdoc Lint provides features such as NumPy style docstring checking in Python code.\n\n# What is NumPy-style docstring?\n\nDescriptions of Python functions, modules, or classes written in the following format.\n\n```py\ndef sample_func(sample_arg_1, sample_arg_2=100, sample_arg_3='Apple'):\n    \"\"\"\n    Sample function description.\n\n    Parameters\n    ----------\n    sample_arg_1 : int\n        First sample argument description.\n    sample_arg_2 : int, default 100\n        Second sample argument description.\n    sample_arg_3 : str, default 'Apple'\n        Third sample argument description.\n\n    Returns\n    ----------\n    sample_return_value : int\n        Sample return value.\n    \"\"\"\n    return 100\n```\n\nFor more details, please see [A Guide to NumPy/SciPy Documentation](https://docs.scipy.org/doc/numpy/docs/howto_document.html).\n\n# Main features\n\n- Check lacked docstring description.\n- Check arguments and docstring `Parameters` section mismatching.\n    - Also will be checked argument default value and docstring optionally.\n- Check arguments order.\n- Check return value and docstring `Returns` section mismatching.\n- Check Jupyter notebook's docstring also.\n\n# Dependencies\n\n## Python version\n\n- Python 3.6 or later.\n\n## Libraries\n\n- six\n\n# Installing\n\n```\n$ pip install numdoclint\n```\n\n# Examples\n\n## Python interface\n\n### Check single module\n\nA single module will be checked with the `check_python_module` function.\n\n```py\n\u003e\u003e\u003e import numdoclint\n\u003e\u003e\u003e lint_info_list = numdoclint.check_python_module(\n...     py_module_path='../pandas/pandas/core/arrays/array_.py')\n```\n\nThen Lint results will be displayed on standard output, as followed:\n\n```\n../pandas/pandas/core/arrays/array_.py::array\nThe function description is not set to docstring.\n\n../pandas/pandas/core/arrays/array_.py::array\nThere is an argument whose explanation does not exist in docstring.\nTarget argument name: data\n\n...\n```\n\nList of dicts will be returned, as followed:\n\n```py\n\u003e\u003e\u003e lint_info_list\n\n[{'module_path': '../pandas/pandas/core/arrays/array_.py',\n  'func_name': 'array',\n  'info_id': 6,\n  'info': 'The function description is not set to docstring.'},\n {'module_path': '../pandas/pandas/core/arrays/array_.py',\n  'func_name': 'array',\n  'info_id': 2,\n  'info': 'There is an argument whose explanation does not exist in docstring.\\nTarget argument name: data'},\n...\n```\n\n### Check modules recursively\n\nIf execute `check_python_module_recursively` function, then Numdoc Lint will check target directory recursively.\n\n```py\n\u003e\u003e\u003e import numdoclint\n\n\u003e\u003e\u003e lint_info_list = numdoclint.check_python_module_recursively(\n...     dir_path='../numpy/')\n```\n\n```py\n\u003e\u003e\u003e import pandas as pd\n\u003e\u003e\u003e df = pd.DataFrame(data=lint_info_list)\n\u003e\u003e\u003e df.head(n=3)\n```\n\n\u003ctable border=\"1\" class=\"dataframe\"\u003e\u003cthead\u003e\u003ctr style=\"text-align: right;\"\u003e\u003cth\u003e\u003c/th\u003e\u003cth\u003efunc_name\u003c/th\u003e\u003cth\u003einfo\u003c/th\u003e\u003cth\u003einfo_id\u003c/th\u003e\u003cth\u003emodule_path\u003c/th\u003e\u003c/tr\u003e\u003c/thead\u003e\u003ctbody\u003e\u003ctr\u003e\u003cth\u003e0\u003c/th\u003e\u003ctd\u003esetup\u003c/td\u003e\u003ctd\u003eThe function description is not set to docstring.\u003c/td\u003e\u003ctd\u003e6\u003c/td\u003e\u003ctd\u003e../numpy/benchmarks/benchmarks/bench_app.py\u003c/td\u003e\u003c/tr\u003e\u003ctr\u003e\u003cth\u003e1\u003c/th\u003e\u003ctd\u003esetup\u003c/td\u003e\u003ctd\u003eThere is an argument whose explanation does no...\u003c/td\u003e\u003ctd\u003e2\u003c/td\u003e\u003ctd\u003e../numpy/benchmarks/benchmarks/bench_app.py\u003c/td\u003e\u003c/tr\u003e\u003ctr\u003e\u003cth\u003e2\u003c/th\u003e\u003ctd\u003esetup\u003c/td\u003e\u003ctd\u003eWhile the return value exists in the function,...\u003c/td\u003e\u003ctd\u003e9\u003c/td\u003e\u003ctd\u003e../numpy/benchmarks/benchmarks/bench_app.py\u003c/td\u003e\u003c/tr\u003e\u003c/tbody\u003e\u003c/table\u003e\n\n```py\n\u003e\u003e\u003e df[100:103]\n```\n\n\u003ctable border=\"1\" class=\"dataframe\"\u003e\u003cthead\u003e\u003ctr style=\"text-align: right;\"\u003e\u003cth\u003e\u003c/th\u003e\u003cth\u003efunc_name\u003c/th\u003e\u003cth\u003einfo\u003c/th\u003e\u003cth\u003einfo_id\u003c/th\u003e\u003cth\u003emodule_path\u003c/th\u003e\u003c/tr\u003e\u003c/thead\u003e\u003ctbody\u003e\u003ctr\u003e\u003cth\u003e100\u003c/th\u003e\u003ctd\u003etime_bincount\u003c/td\u003e\u003ctd\u003eThe function description is not set to docstring.\u003c/td\u003e\u003ctd\u003e6\u003c/td\u003e\u003ctd\u003e../numpy/benchmarks/benchmarks/bench_function_...\u003c/td\u003e\u003c/tr\u003e\u003ctr\u003e\u003cth\u003e101\u003c/th\u003e\u003ctd\u003etime_weights\u003c/td\u003e\u003ctd\u003eThe function description is not set to docstring.\u003c/td\u003e\u003ctd\u003e6\u003c/td\u003e\u003ctd\u003e../numpy/benchmarks/benchmarks/bench_function_...\u003c/td\u003e\u003c/tr\u003e\u003ctr\u003e\u003cth\u003e102\u003c/th\u003e\u003ctd\u003esetup\u003c/td\u003e\u003ctd\u003eThe function description is not set to docstring.\u003c/td\u003e\u003ctd\u003e6\u003c/td\u003e\u003ctd\u003e../numpy/benchmarks/benchmarks/bench_function_...\u003c/td\u003e\u003c/tr\u003e\u003c/tbody\u003e\u003c/table\u003e\n\n### Verbose setting\n\nIf you only need lint result list, and not necessary standard output, then set verbose argument to 0 and stdout will be disabled.\n\n```py\n\u003e\u003e\u003e lint_info_list = numdoclint.check_python_module(\n...     py_module_path='../pandas/pandas/core/arrays/array_.py',\n...     verbose=0)\n```\n\n### Ignore specified functions\n\nIf you want to skip functions with a specific prefix, set prefix names to the `skip_decorator_name_list` argument (default is `[test_]`).\n\n```py\n\u003e\u003e\u003e lint_info_list = numdoclint.check_python_module(\n...     py_module_path='../pandas/pandas/core/arrays/array_.py',\n...     ignore_func_name_prefix_list=['test_', '_main', '__init__'])\n```\n\n### Ignore specified IDs check\n\nYou can specify IDs to `ignore_info_id_list` argument to ignore.\nThe ID corresponds to the return value's `info_id`.\n\n```py\n# sample.py\n\ndef sample_func():\n    \"\"\"\n    Sample function.\n\n    Returns\n    -------\n    price : int\n        Sample price\n    \"\"\"\n    pass\n```\n\n```py\n\u003e\u003e\u003e import numdoclint\n\u003e\u003e\u003e lint_info_list = numdoclint.check_python_module(\n...     py_module_path='./sample.py',\n...     verbose=0)\n\u003e\u003e\u003e lint_info_list\n[{'module_path': './sample.py',\n  'func_name': 'sample_func',\n  'info_id': 12,\n  'info': 'While the return value document exists in docstring, the return value does not exist in the function.'}]\n\n\u003e\u003e\u003e lint_info_list = numdoclint.check_python_module(\n...     py_module_path='./sample.py',\n...     ignore_info_id_list=[12],\n...     verbose=0)\n\u003e\u003e\u003e lint_info_list\n[]\n```\n\nOr you can also specify ID's constant to argument.\n\n```py\n\u003e\u003e\u003e lint_info_list = numdoclint.check_python_module(\n...     py_module_path='./sample.py',\n...     ignore_info_id_list=[\n...         numdoclint.INFO_ID_LACKED_RETURN_VAL,\n...     ],\n...     verbose=0)\n\u003e\u003e\u003e lint_info_list\n[]\n```\n\n### Parameters default check\n\nBy default, the following docstring `Parameters` default specification will not be checked.\n\n```py\ndef sample_func(price=100):\n    \"\"\"\n    Sample function.\n\n    Parameters\n    ----------\n    price : int, default 100\n        Sample price.\n    \"\"\"\n    pass\n```\n\nIf 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.\n\n```py\n\u003e\u003e\u003e lint_info_list = numdoclint.check_python_module(\n...     py_module_path='../pandas/pandas/core/frame.py',\n...     enable_default_or_optional_doc_check=True)\n```\n\n```\n...\n../pandas/pandas/core/frame.py::to_dict\nWhile there is no description of default value in docstring, there is a default value on the argument side.\nArgument name: orient\nArgument default value: \"dict\"\n...\n```\n\n### Check Jupyter notebook\n\nBy using the `check_jupyter_notebook` and `check_jupyter_notebook_recursively` interface, you can check Jupyter notebooks as well as Python modules.\n\n```py\ncheck_result_list = numdoclint.check_jupyter_notebook(\n    notebook_path='./sample_notebook.ipynb')\n```\n\n```py\ncheck_result_list = numdoclint.check_jupyter_notebook_recursively(\n    dir_path='./sample_dir/')\n```\n\n`ignore_func_name_prefix_list`, `ignore_info_id_list`, and `enable_default_or_optional_doc_check` arguments described above are also available.\n\n## Command line interface\n\nYou can run the check as well with the following command:\n\n```\n$ numdoclint -p ./sample/path.py\n```\n\nThe following arguments are provided. Only `--path` argument is required, other arguments are optional.\n\n```\n  -h, --help            show this help message and exit\n  -p PATH, --path PATH  Python module file path, Jupyter notebook path, or\n                        directory path.\n  -r, --check_recursively\n                        If specified, check files recursively.In that case,\n                        you need to specify the directory in the path\n                        argument.\n  -j, --is_jupyter      If specified, check target will become Jupyter\n                        notebook. If not, Python module will be checked.\n  -f IGNORE_FUNC_NAME_PREFIX_LIST, --ignore_func_name_prefix_list IGNORE_FUNC_NAME_PREFIX_LIST\n                        A prefix list of function name conditions to ignore.\n                        e.g., 'test_,sample_'. Comma separated string is\n                        acceptable.\n  -i IGNORE_INFO_ID_LIST, --ignore_info_id_list IGNORE_INFO_ID_LIST\n                        List of IDs to ignore lint checking. e.g, '1,2,3'. Comma\n                        separated integer is acceptable.\n  -o, --enable_default_or_optional_doc_check\n                        If specified, the `default` and `optional` stringin\n                        docstring will be checked.\n  -d SKIP_DECORATOR_NAME_LIST, --skip_decorator_name_list SKIP_DECORATOR_NAME_LIST\n                        If a decorator name in this list is set to function,\n                        that function will not be checked. Specify if\n                        necessary for docstring-related decorators. Note: only\n                        available when check Python module, not supported\n                        Jupyter notebook.\n```\n\n### Example of checking Python module recursively:\n\n```\n$ numdoclint -p ./sample/dir/ -r\n```\n\n### Example of checking Jupyter notebook:\n\n```\n$ numdoclint -j -p ./sample/path.ipynb\n```\n\n### Example of checking Jupyter notebook recursively:\n\n```\n$ numdoclint -j -r -p ./sample/dir/\n```\n\n# Lint condition examples\n\n## Lacked docstring function description\n\n```py\n# sample.py\n\ndef sample_func(price):\n    \"\"\"\n    Parameters\n    ----------\n    name : str\n        Sample name.\n    \"\"\"\n    pass\n```\n\n```py\n\u003e\u003e\u003e lint_info_list = numdoclint.check_python_module(\n...     py_module_path='./sample.py')\n\n./sample.py::sample_func\nThe function description is not set to docstring.\n```\n\n## Lacked argument\n\n```py\n# sample.py\n\ndef sample_func(price):\n    \"\"\"\n    Sample function.\n\n    Parameters\n    ----------\n    price : int\n        Sample price.\n    lacked_arg : str\n        Sample string.\n    \"\"\"\n    pass\n```\n\n```py\n\u003e\u003e\u003e lint_info_list = numdoclint.check_python_module(\n...     py_module_path='./sample.py')\n\n./sample.py::sample_func\nAn argument exists in docstring does not exists in the actual argument.\nLacked argument name: lacked_arg\n```\n\n## Lacked docstring parameter description\n\n```py\n# sample.py\n\ndef sample_func(price, lacked_arg):\n    \"\"\"\n    Sample function.\n\n    Parameters\n    ----------\n    price : int\n        Sample price.\n    \"\"\"\n    pass\n```\n\n```py\n\u003e\u003e\u003e lint_info_list = numdoclint.check_python_module(\n...     py_module_path='./sample.py')\n\n./sample.py::sample_func\nThere is an argument whose explanation does not exist in docstring.\nTarget argument name: lacked_arg\n```\n\n## Lacked docstring parameter type information\n\n```py\n# sample.py\n\ndef sample_func(price):\n    \"\"\"\n    Sample function.\n\n    Parameters\n    ----------\n    price\n        Sample price (type not specified).\n    \"\"\"\n    pass\n```\n\n```py\n\u003e\u003e\u003e lint_info_list = numdoclint.check_python_module(\n...     py_module_path='./sample.py')\n\n./sample.py::sample_func\nMissing docstring argument type information.\nTarget argument: price\n```\n\n## Lacked docstring parameter description\n\n```py\n# sample.py\n\ndef sample_func(price, name):\n    \"\"\"\n    Sample function.\n\n    Parameters\n    ----------\n    price : int\n    name : str\n    \"\"\"\n    pass\n```\n\n```py\n\u003e\u003e\u003e lint_info_list = numdoclint.check_python_module(\n...     py_module_path='./sample.py')\n\n./sample.py::sample_func\nMissing docstring argument information.\nArgument name: price\n\n./sample.py::sample_func\nMissing docstring argument information.\nArgument name: name\n```\n\n## Argument and docstring parameter order mismatching\n\n```py\n# sample.py\n\ndef sample_func(price, name):\n    \"\"\"\n    Sample function.\n\n    Parameters\n    ----------\n    name : str\n        Sample name.\n    price : int\n        Sample price.\n    \"\"\"\n    pass\n```\n\n```py\n\u003e\u003e\u003e lint_info_list = numdoclint.check_python_module(\n...     py_module_path='./sample.py')\n\n./sample.py::sample_func\nThe order of the argument and docstring is different.\nOrder of arguments: ['price', 'name']\nOrder of docstring parameters: ['name', 'price']\n```\n\n## Lacked docstring default value description\n\nNote: Only enabled when `enable_default_or_optional_doc_check=True` argument specified.\n\n```py\n# sample.py\n\ndef sample_func(price=100):\n    \"\"\"\n    Sample function.\n\n    Parameters\n    ----------\n    price : int\n        Sample price.\n    \"\"\"\n    pass\n```\n\n```py\n\u003e\u003e\u003e lint_info_list = numdoclint.check_python_module(\n...     py_module_path='./sample.py',\n...     enable_default_or_optional_doc_check=True)\n\n./sample.py::sample_func\nWhile there is no description of default value in docstring, there is a default value on the argument side.\nArgument name: price\nArgument default value: 100\n```\n\nGood patterns:\n\n1. `, default xxx` specified (mainly used in Pandas):\n\n```py\n# sample.py\n\ndef sample_func(price=100):\n    \"\"\"\n    Sample function.\n\n    Parameters\n    ----------\n    price : int, default 100\n        Sample price.\n    \"\"\"\n    pass\n```\n\n2. `, default is xxx` specified (mainly used in NumPy):\n\n```py\n# sample.py\n\ndef sample_func(price=100):\n    \"\"\"\n    Sample function.\n\n    Parameters\n    ----------\n    price : int, default is 100\n        Sample price.\n    \"\"\"\n    pass\n```\n\n3. `(default 100)` specified (rarely used in Pands):\n\n```py\n# sample.py\n\ndef sample_func(price=100):\n    \"\"\"\n    Sample function.\n\n    Parameters\n    ----------\n    price : int (default 100)\n        Sample price.\n    \"\"\"\n    pass\n```\n\n## Lacked argument default value, while docstring default value exists.\n\nNote: Only enabled when `enable_default_or_optional_doc_check=True` argument specified.\n\n```py\n# sample.py\n\ndef sample_func(price):\n    \"\"\"\n    Sample function.\n\n    Parameters\n    ----------\n    price : int, default 100\n        Sample price.\n    \"\"\"\n    pass\n```\n\n```py\n\u003e\u003e\u003e lint_info_list = numdoclint.check_python_module(\n...     py_module_path='./sample.py',\n...     enable_default_or_optional_doc_check=True)\n\n./sample.py::sample_func\nThe default value described in docstring does not exist in the actual argument.\nArgment name: price\nDocstring default value: 100\n```\n\n## Lacked docstring of return value\n\n```py\n# sample.py\n\ndef sample_func():\n    \"\"\"\n    Sample function.\n    \"\"\"\n    return 100\n```\n\n```\n\u003e\u003e\u003e lint_info_list = numdoclint.check_python_module(\n...     py_module_path='./sample.py',\n...     enable_default_or_optional_doc_check=True)\n\n./sample.py::sample_func\nWhile the return value exists in the function, the return value document does not exist in docstring.\n```\n\n## Lacked docstring return value description\n\n```py\n# sample.py\n\ndef sample_func():\n    \"\"\"\n    Sample function.\n\n    Returns\n    -------\n    price : int\n    \"\"\"\n    return 100\n```\n\n```py\n\u003e\u003e\u003e lint_info_list = numdoclint.check_python_module(\n...     py_module_path='./sample.py')\n\n./sample.py::sample_func\nDocstring description of return value is missing.\nReturn value name: price\nReturn value type: int\n```\n\n## Lacked return value, while `Returns` docstring section exists\n\n```py\n# sample.py\n\ndef sample_func():\n    \"\"\"\n    Sample function.\n\n    Returns\n    -------\n    price : int\n        Sample price\n    \"\"\"\n    pass\n```\n\n```py\n\u003e\u003e\u003e lint_info_list = numdoclint.check_python_module(\n\u003e\u003e\u003e     py_module_path='./sample.py')\n\n./sample.py::sample_func\nWhile the return value document exists in docstring, the return value does not exist in the function.\n```\n\n# Testing and Lint\n\nThe following library modules are used for testing and lint.\n\n- pytest==4.3.1\n- pytest-cov==2.7.1\n- voluptuous==0.12.1\n- flake8==3.7.8\n- autoflake==1.3\n- autopep8==1.4.4\n- isort==4.3.16\n\nCommand to run overall tests and lint:\n\n```\n$ python ./run_all_tests_and_lint.py\n```\n\nCommand to run the entire test:\n\n```\n$ pytest --cov=numdoclint tests/ -v\n```\n\nCommand to run the autoflake:\n\n```\n$ autoflake --in-place --remove-unused-variables --remove-all-unused-imports -r ./\n```\n\nCommand to run the autopep8:\n\n```\n$ autopep8 --in-place --aggressive --aggressive --recursive ./\n```\n\nCommand to run the isort:\n\n```\n$ isort -rc ./\n```\n\nCommand to run the flake8:\n\n```\n$ flake8 ./\n```\n\n# PyPI\n\nThe following library are used for PyPI uploading.\n\n- twine==1.13.0\n- wheel==0.36.2\n\nBuild command:\n\n```\n$ python build.py\n```\n\nUpload to TestPyPI:\n\n```\n$ twine upload --repository-url https://test.pypi.org/legacy/ dist/*\n```\n\nInstall from TestPyPI:\n\n```\n$ pip install --index-url https://testpypi.python.org/simple/ numdoclint\n```\n\nUpload to PyPI:\n\n```\n$ twine upload dist/*\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsimon-ritchie%2Fnumdoclint","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsimon-ritchie%2Fnumdoclint","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsimon-ritchie%2Fnumdoclint/lists"}