├── .github └── workflows │ ├── python-publish-ext.yml │ └── python-publish.yml ├── .gitignore ├── README.md ├── docstring_generator ├── __init__.py └── new_gen_docs.py ├── examples └── mixed_before_tmp.py ├── license.md ├── poetry.lock ├── pyproject.toml └── tests └── tmp ├── __init__.py ├── file_a_broken_after_second_iter.py ├── file_a_one_iteration.py └── tmp.py /.github/workflows/python-publish-ext.yml: -------------------------------------------------------------------------------- 1 | # This workflows will upload a Python Package using Twine when a release is created 2 | # For more information see: https://help.github.com/en/actions/language-and-framework-guides/using-python-with-github-actions#publishing-to-package-registries 3 | 4 | name: Upload Extension Package 5 | 6 | on: 7 | release: 8 | types: [created] 9 | 10 | jobs: 11 | 12 | deploy: 13 | runs-on: ubuntu-latest 14 | 15 | steps: 16 | - uses: actions/checkout@v3 17 | 18 | - name: Set up Python 19 | uses: actions/setup-python@v4 20 | with: 21 | python-version: '3.11' 22 | 23 | - name: Install dependencies 24 | run: | 25 | python -m pip install --upgrade pip 26 | pip install setuptools wheel twine pybind11 27 | 28 | - name: Build and publish 29 | env: 30 | TWINE_USERNAME: ${{ secrets.PYPI_USERNAME }} 31 | TWINE_PASSWORD: ${{ secrets.PYPI_PASSWORD }} 32 | run: | 33 | python setup.py sdist bdist_wheel 34 | twine upload dist/* 35 | -------------------------------------------------------------------------------- /.github/workflows/python-publish.yml: -------------------------------------------------------------------------------- 1 | # This workflows will upload a Python Package using Twine when a release is created 2 | # For more information see: https://help.github.com/en/actions/language-and-framework-guides/using-python-with-github-actions#publishing-to-package-registries 3 | 4 | name: Upload Python Package 5 | 6 | on: 7 | release: 8 | types: [created] 9 | 10 | jobs: 11 | 12 | deploy: 13 | runs-on: ubuntu-latest 14 | 15 | steps: 16 | - uses: actions/checkout@v3 17 | 18 | - name: Set up Python 19 | uses: actions/setup-python@v4 20 | with: 21 | python-version: '3.11' 22 | 23 | - name: Install dependencies 24 | run: | 25 | python -m pip install --upgrade pip 26 | pip install poetry==1.2.1 twine 27 | 28 | - name: Build and publish 29 | env: 30 | TWINE_USERNAME: ${{ secrets.PYPI_USERNAME }} 31 | TWINE_PASSWORD: ${{ secrets.PYPI_PASSWORD }} 32 | run: | 33 | poetry build 34 | twine upload dist/* 35 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | 6 | # C extensions 7 | *.so 8 | 9 | # Distribution / packaging 10 | .Python 11 | build/ 12 | develop-eggs/ 13 | dist/ 14 | downloads/ 15 | eggs/ 16 | .eggs/ 17 | lib/ 18 | lib64/ 19 | parts/ 20 | sdist/ 21 | var/ 22 | wheels/ 23 | pip-wheel-metadata/ 24 | share/python-wheels/ 25 | *.egg-info/ 26 | .installed.cfg 27 | *.egg 28 | MANIFEST 29 | 30 | # PyInstaller 31 | # Usually these files are written by a python script from a template 32 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 33 | *.manifest 34 | *.spec 35 | 36 | # Installer logs 37 | pip-log.txt 38 | pip-delete-this-directory.txt 39 | 40 | # Unit test / coverage reports 41 | htmlcov/ 42 | .tox/ 43 | .nox/ 44 | .coverage 45 | .coverage.* 46 | .cache 47 | nosetests.xml 48 | coverage.xml 49 | *.cover 50 | *.py,cover 51 | .hypothesis/ 52 | .pytest_cache/ 53 | 54 | # Translations 55 | *.mo 56 | *.pot 57 | 58 | # Django stuff: 59 | *.log 60 | local_settings.py 61 | db.sqlite3 62 | db.sqlite3-journal 63 | 64 | # Flask stuff: 65 | instance/ 66 | .webassets-cache 67 | 68 | # Scrapy stuff: 69 | .scrapy 70 | 71 | # Sphinx documentation 72 | docs/_build/ 73 | 74 | # PyBuilder 75 | target/ 76 | 77 | # Jupyter Notebook 78 | .ipynb_checkpoints 79 | 80 | # IPython 81 | profile_default/ 82 | ipython_config.py 83 | 84 | # pyenv 85 | .python-version 86 | 87 | # pipenv 88 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. 89 | # However, in case of collaboration, if having platform-specific dependencies or dependencies 90 | # having no cross-platform support, pipenv may install dependencies that don't work, or not 91 | # install all needed dependencies. 92 | #Pipfile.lock 93 | 94 | # PEP 582; used by e.g. github.com/David-OConnor/pyflow 95 | __pypackages__/ 96 | 97 | # Celery stuff 98 | celerybeat-schedule 99 | celerybeat.pid 100 | 101 | # SageMath parsed files 102 | *.sage.py 103 | 104 | # Environments 105 | .env 106 | .venv 107 | env/ 108 | venv/ 109 | ENV/ 110 | env.bak/ 111 | venv.bak/ 112 | 113 | # Spyder project settings 114 | .spyderproject 115 | .spyproject 116 | 117 | # Rope project settings 118 | .ropeproject 119 | 120 | # mkdocs documentation 121 | /site 122 | 123 | # mypy 124 | .mypy_cache/ 125 | .dmypy.json 126 | dmypy.json 127 | 128 | # Pyre type checker 129 | .pyre/ 130 | .docstring_generator/ 131 | /venv_3_10/ 132 | /src/.idea/ 133 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![Python 3.10](https://img.shields.io/badge/python-3-blue.svg)](https://www.python.org/downloads/) 2 | [![PyPI version](https://badge.fury.io/py/docstring-generator.svg)](https://badge.fury.io/py/docstring-generator) 3 | [![Code style: black](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/psf/black) 4 | [![Imports: isort](https://img.shields.io/badge/%20imports-isort-%231674b1?style=flat&labelColor=ef8336)](https://pycqa.github.io/isort/) 5 | [![](https://img.shields.io/pypi/dm/docstring-generator.svg)](https://pypi.org/project/docstring-generator/) 6 | 7 | # docstring_generator 8 | Auto generate docstring from type-hints for python functions and class methods. 9 | 10 | ## How to use it 11 | 12 | ```shell 13 | gendocs_new file.py 14 | ``` 15 | 16 | ```shell 17 | gendocs_new mydir/ 18 | ``` 19 | 20 | ## Options 21 | 22 | ### style 23 | 24 | - `--style` 25 | - Docstring style [numpy, google, rest]. [default: numpy] 26 | 27 | ### Add additional information before running `gendocs_new` 28 | 29 | - when adding `$` into your docstring these will then be replaced with parameter at this index 30 | - Example: 31 | ```python 32 | from typing import List 33 | 34 | 35 | def foo(val_a: int, val_b: List[int]): 36 | """ 37 | Lorem ipsum dolor sit amet, consetetur sadipscing elitr, 38 | sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam 39 | 40 | $1 Lorem ipsum dolor sit amet 41 | $2 nonumy eirmod tempor invidun 42 | """ 43 | ``` 44 | will become (here with numpy style) 45 | ```python 46 | from typing import List 47 | 48 | 49 | def foo(val_a: int, val_b: List[int]): 50 | """ 51 | Lorem ipsum dolor sit amet, consetetur sadipscing elitr, 52 | sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam 53 | 54 | Parameters 55 | ---------- 56 | val_a : argument of type int 57 | Lorem ipsum dolor sit amet 58 | val_b : argument of type List(int) 59 | nonumy eirmod tempor invidun 60 | 61 | """ 62 | ``` 63 | 64 | ## FAQ 65 | 66 | ### what happens if I re-run the docstring creation? 67 | 68 | - nothing if all stays the same, changed parameter descriptions will be ignored only changes of the function header will be used 69 | 70 | ## Examples 71 | - An example can be found under examples 72 | 73 | ## Installing 74 | 75 | - pip install docstring-generator 76 | 77 | ## Dependency `docstring-generator-ext` 78 | 79 | - this extension is the heart of this project and written with pybind11 (c++) 80 | 81 | ## Versioning 82 | 83 | - For the versions available, see the tags on this repository. 84 | 85 | ## Authors 86 | 87 | - Felix Eisenmenger 88 | 89 | ## License 90 | 91 | - MIT License (MIT) -------------------------------------------------------------------------------- /docstring_generator/__init__.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | """ 4 | @created: 01.08.21 5 | @author: felix 6 | """ 7 | -------------------------------------------------------------------------------- /docstring_generator/new_gen_docs.py: -------------------------------------------------------------------------------- 1 | import pathlib 2 | 3 | import click 4 | import docstring_generator_ext 5 | 6 | 7 | @click.command() 8 | @click.argument("path") 9 | @click.option( 10 | "--style", default="numpy", help="Docstring style [numpy, rest, google].", show_default=True 11 | ) 12 | def main(path: str, style: str) -> None: 13 | path_ = pathlib.Path(path) 14 | 15 | docstring_style = docstring_generator_ext.DocstringFormatStyle.NUMPY 16 | if style == "rest": 17 | docstring_style = docstring_generator_ext.DocstringFormatStyle.reST 18 | if style == "google": 19 | docstring_style = docstring_generator_ext.DocstringFormatStyle.GOOGLE 20 | 21 | if not path_.exists(): 22 | return 23 | 24 | if path_.is_dir(): 25 | for file in path_.glob("**/*.py"): 26 | docstring_generator_ext.parse_file(file.absolute().as_posix(), docstring_style) 27 | 28 | if path_.is_file() and path_.name.endswith(".py"): 29 | docstring_generator_ext.parse_file(path_.absolute().as_posix(), docstring_style) 30 | 31 | 32 | if __name__ == "__main__": 33 | main() 34 | -------------------------------------------------------------------------------- /examples/mixed_before_tmp.py: -------------------------------------------------------------------------------- 1 | from datetime import datetime 2 | from typing import Callable, Dict, Optional, Union 3 | 4 | 5 | def function_name(): 6 | pass 7 | 8 | 9 | def function_name_args(arg1, arg2, arg3: Optional[bool]): 10 | """ 11 | Parameters 12 | ---------- 13 | arg1 : [Argument] 14 | arg2 : [Argument] 15 | arg3 : Optional[bool] [Argument] 16 | 17 | """ 18 | if not dict: 19 | return "" 20 | res = {} 21 | for key, val in annotations.items(): 22 | print(f"{val['default'] = }") 23 | if default_val := val["default"] != "_empty": 24 | res[key] = f"{val['annotation']} = {default_val}" 25 | else: 26 | res[key] = val["annotation"] 27 | return ", ".join([f"{key}: {val}" for key, val in res.items()]) 28 | 29 | 30 | def function_name_defaults( 31 | arg1, 32 | arg2: str = "hello", 33 | arg3: Callable = datetime.now, 34 | ) -> int: 35 | """ 36 | Lorem ipsum dolor samit even more text 37 | 38 | Parameters 39 | ---------- 40 | arg1 : [Argument] 41 | arg2 : str, optional, default: 'hello' [Argument] 42 | more precise information about the required callable 43 | arg3 : Callable, optional, default: datetime.now [Argument] 44 | 45 | Returns 46 | ------- 47 | int 48 | """ 49 | 50 | return 2 * 2 51 | 52 | 53 | def function_name_star_args(*args): 54 | """ 55 | Parameters 56 | ---------- 57 | args : [Variadic arguments] 58 | 59 | """ 60 | ... 61 | 62 | 63 | def function_name_kwargs(**kwargs): 64 | """ 65 | Parameters 66 | ---------- 67 | kwargs : [Keyword arguments] 68 | 69 | """ 70 | pass 71 | 72 | 73 | def function_name_args_kwargs(*args: tuple, **kwargs: dict): 74 | """ 75 | Parameters 76 | ---------- 77 | args : tuple [Variadic arguments] 78 | kwargs : dict [Keyword arguments] 79 | 80 | """ 81 | pass 82 | 83 | 84 | def function_name_pos_only(pos1, /, pos2, pos3): 85 | """ 86 | Parameters 87 | ---------- 88 | pos1 : [Positional only argument] 89 | pos2 : [Argument] 90 | pos3 : [Argument] 91 | 92 | """ 93 | pass 94 | 95 | 96 | def function_name_kwargs_only(arg1, arg2: int | str = 2, *, kwarg1, kwarg2): 97 | """ 98 | Parameters 99 | ---------- 100 | arg1 : [Argument] 101 | arg2 : Union[int, str], optional, default: 2 [Argument] 102 | kwarg1 : [Keyword only argument] 103 | kwarg2 : [Keyword only argument] 104 | 105 | """ 106 | pass 107 | 108 | 109 | def function_name_pos_only_kwargs_only(pos1, pos2: int = 3, /, *, kwarg1, kwarg2="2"): 110 | """ 111 | Parameters 112 | ---------- 113 | pos1 : [Positional only argument] 114 | pos2 : int, optional, default: 3 [Positional only argument] 115 | kwarg1 : [Keyword only argument] 116 | kwarg2 :default: '2' [Keyword only argument] 117 | 118 | """ 119 | pass 120 | 121 | 122 | def function_without_custom_docstring(param_a: str, param_b: dict): 123 | """ 124 | Parameters 125 | ---------- 126 | param_a : str [Argument] 127 | param_b : dict [Argument] 128 | 129 | """ 130 | pass 131 | 132 | 133 | def function_with_custom_docstring(param_a: int, param_b: Callable) -> str: 134 | """ 135 | Lorem ipsum dolor samit even more text 136 | 137 | Parameters 138 | ---------- 139 | param_a : int [Argument] 140 | param_b : Callable [Argument] 141 | more precise information about the required callable 142 | 143 | Returns 144 | ------- 145 | str 146 | """ 147 | pass 148 | 149 | 150 | def function_without_complex_type(param_a: list[str], param_b: Dict[Union[int, str], str | bool]): 151 | """ 152 | Some useful information about this function 153 | 154 | Parameters 155 | ---------- 156 | param_a : list[str] [Argument] 157 | param_b : Dict[Union[int, str], Union[str, bool]] [Argument] 158 | 159 | """ 160 | pass 161 | 162 | 163 | class Dummy: 164 | """ 165 | Some useful information about this class 166 | """ 167 | 168 | attr_a: str = "Hello" 169 | attr_b: int 170 | 171 | def __init__(self): 172 | """ 173 | Parameters 174 | ---------- 175 | self : [Argument] 176 | 177 | """ 178 | pass 179 | 180 | def some_other_method(self, param_a: int): 181 | """ 182 | Lorem ipsum dolor some_method 183 | 184 | Parameters 185 | ---------- 186 | self : [Argument] 187 | more precise information about the required callable 188 | param_a : int [Argument] 189 | 190 | """ 191 | 192 | return self.attr_b 193 | 194 | @classmethod 195 | def some_classmethod(cls): 196 | """ 197 | Lorem ipsum dolor some_classmethod 198 | 199 | Parameters 200 | ---------- 201 | cls : [Argument] 202 | 203 | """ 204 | 205 | return cls.attr_b 206 | -------------------------------------------------------------------------------- /license.md: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2023 felix 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 6 | 7 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 8 | 9 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /poetry.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Poetry 1.7.1 and should not be changed by hand. 2 | 3 | [[package]] 4 | name = "attrs" 5 | version = "22.1.0" 6 | description = "Classes Without Boilerplate" 7 | optional = false 8 | python-versions = ">=3.5" 9 | files = [ 10 | {file = "attrs-22.1.0-py2.py3-none-any.whl", hash = "sha256:86efa402f67bf2df34f51a335487cf46b1ec130d02b8d39fd248abfd30da551c"}, 11 | {file = "attrs-22.1.0.tar.gz", hash = "sha256:29adc2665447e5191d0e7c568fde78b21f9672d344281d0c6e1ab085429b22b6"}, 12 | ] 13 | 14 | [package.extras] 15 | dev = ["cloudpickle", "coverage[toml] (>=5.0.2)", "furo", "hypothesis", "mypy (>=0.900,!=0.940)", "pre-commit", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "sphinx", "sphinx-notfound-page", "zope.interface"] 16 | docs = ["furo", "sphinx", "sphinx-notfound-page", "zope.interface"] 17 | tests = ["cloudpickle", "coverage[toml] (>=5.0.2)", "hypothesis", "mypy (>=0.900,!=0.940)", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "zope.interface"] 18 | tests-no-zope = ["cloudpickle", "coverage[toml] (>=5.0.2)", "hypothesis", "mypy (>=0.900,!=0.940)", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins"] 19 | 20 | [[package]] 21 | name = "black" 22 | version = "24.3.0" 23 | description = "The uncompromising code formatter." 24 | optional = false 25 | python-versions = ">=3.8" 26 | files = [ 27 | {file = "black-24.3.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:7d5e026f8da0322b5662fa7a8e752b3fa2dac1c1cbc213c3d7ff9bdd0ab12395"}, 28 | {file = "black-24.3.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9f50ea1132e2189d8dff0115ab75b65590a3e97de1e143795adb4ce317934995"}, 29 | {file = "black-24.3.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e2af80566f43c85f5797365077fb64a393861a3730bd110971ab7a0c94e873e7"}, 30 | {file = "black-24.3.0-cp310-cp310-win_amd64.whl", hash = "sha256:4be5bb28e090456adfc1255e03967fb67ca846a03be7aadf6249096100ee32d0"}, 31 | {file = "black-24.3.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:4f1373a7808a8f135b774039f61d59e4be7eb56b2513d3d2f02a8b9365b8a8a9"}, 32 | {file = "black-24.3.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:aadf7a02d947936ee418777e0247ea114f78aff0d0959461057cae8a04f20597"}, 33 | {file = "black-24.3.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:65c02e4ea2ae09d16314d30912a58ada9a5c4fdfedf9512d23326128ac08ac3d"}, 34 | {file = "black-24.3.0-cp311-cp311-win_amd64.whl", hash = "sha256:bf21b7b230718a5f08bd32d5e4f1db7fc8788345c8aea1d155fc17852b3410f5"}, 35 | {file = "black-24.3.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:2818cf72dfd5d289e48f37ccfa08b460bf469e67fb7c4abb07edc2e9f16fb63f"}, 36 | {file = "black-24.3.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:4acf672def7eb1725f41f38bf6bf425c8237248bb0804faa3965c036f7672d11"}, 37 | {file = "black-24.3.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c7ed6668cbbfcd231fa0dc1b137d3e40c04c7f786e626b405c62bcd5db5857e4"}, 38 | {file = "black-24.3.0-cp312-cp312-win_amd64.whl", hash = "sha256:56f52cfbd3dabe2798d76dbdd299faa046a901041faf2cf33288bc4e6dae57b5"}, 39 | {file = "black-24.3.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:79dcf34b33e38ed1b17434693763301d7ccbd1c5860674a8f871bd15139e7837"}, 40 | {file = "black-24.3.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:e19cb1c6365fd6dc38a6eae2dcb691d7d83935c10215aef8e6c38edee3f77abd"}, 41 | {file = "black-24.3.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:65b76c275e4c1c5ce6e9870911384bff5ca31ab63d19c76811cb1fb162678213"}, 42 | {file = "black-24.3.0-cp38-cp38-win_amd64.whl", hash = "sha256:b5991d523eee14756f3c8d5df5231550ae8993e2286b8014e2fdea7156ed0959"}, 43 | {file = "black-24.3.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:c45f8dff244b3c431b36e3224b6be4a127c6aca780853574c00faf99258041eb"}, 44 | {file = "black-24.3.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:6905238a754ceb7788a73f02b45637d820b2f5478b20fec82ea865e4f5d4d9f7"}, 45 | {file = "black-24.3.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d7de8d330763c66663661a1ffd432274a2f92f07feeddd89ffd085b5744f85e7"}, 46 | {file = "black-24.3.0-cp39-cp39-win_amd64.whl", hash = "sha256:7bb041dca0d784697af4646d3b62ba4a6b028276ae878e53f6b4f74ddd6db99f"}, 47 | {file = "black-24.3.0-py3-none-any.whl", hash = "sha256:41622020d7120e01d377f74249e677039d20e6344ff5851de8a10f11f513bf93"}, 48 | {file = "black-24.3.0.tar.gz", hash = "sha256:a0c9c4a0771afc6919578cec71ce82a3e31e054904e7197deacbc9382671c41f"}, 49 | ] 50 | 51 | [package.dependencies] 52 | click = ">=8.0.0" 53 | mypy-extensions = ">=0.4.3" 54 | packaging = ">=22.0" 55 | pathspec = ">=0.9.0" 56 | platformdirs = ">=2" 57 | tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""} 58 | typing-extensions = {version = ">=4.0.1", markers = "python_version < \"3.11\""} 59 | 60 | [package.extras] 61 | colorama = ["colorama (>=0.4.3)"] 62 | d = ["aiohttp (>=3.7.4)", "aiohttp (>=3.7.4,!=3.9.0)"] 63 | jupyter = ["ipython (>=7.8.0)", "tokenize-rt (>=3.2.0)"] 64 | uvloop = ["uvloop (>=0.15.2)"] 65 | 66 | [[package]] 67 | name = "click" 68 | version = "8.1.3" 69 | description = "Composable command line interface toolkit" 70 | optional = false 71 | python-versions = ">=3.7" 72 | files = [ 73 | {file = "click-8.1.3-py3-none-any.whl", hash = "sha256:bb4d8133cb15a609f44e8213d9b391b0809795062913b383c62be0ee95b1db48"}, 74 | {file = "click-8.1.3.tar.gz", hash = "sha256:7682dc8afb30297001674575ea00d1814d808d6a36af415a82bd481d37ba7b8e"}, 75 | ] 76 | 77 | [package.dependencies] 78 | colorama = {version = "*", markers = "platform_system == \"Windows\""} 79 | 80 | [[package]] 81 | name = "colorama" 82 | version = "0.4.5" 83 | description = "Cross-platform colored terminal text." 84 | optional = false 85 | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" 86 | files = [ 87 | {file = "colorama-0.4.5-py2.py3-none-any.whl", hash = "sha256:854bf444933e37f5824ae7bfc1e98d5bce2ebe4160d46b5edf346a89358e99da"}, 88 | {file = "colorama-0.4.5.tar.gz", hash = "sha256:e6c6b4334fc50988a639d9b98aa429a0b57da6e17b9a44f0451f930b6967b7a4"}, 89 | ] 90 | 91 | [[package]] 92 | name = "docstring-generator-ext" 93 | version = "0.0.31" 94 | description = "Generate Docstrings with type-hint information" 95 | optional = false 96 | python-versions = "<3.12" 97 | files = [ 98 | {file = "docstring_generator_ext-0.0.31.tar.gz", hash = "sha256:93d0904c40dfccd73d2cfccf98e17bea95d915a69c692e8d984e2fa872280522"}, 99 | ] 100 | 101 | [package.extras] 102 | test = ["pytest"] 103 | 104 | [[package]] 105 | name = "iniconfig" 106 | version = "1.1.1" 107 | description = "iniconfig: brain-dead simple config-ini parsing" 108 | optional = false 109 | python-versions = "*" 110 | files = [ 111 | {file = "iniconfig-1.1.1-py2.py3-none-any.whl", hash = "sha256:011e24c64b7f47f6ebd835bb12a743f2fbe9a26d4cecaa7f53bc4f35ee9da8b3"}, 112 | {file = "iniconfig-1.1.1.tar.gz", hash = "sha256:bc3af051d7d14b2ee5ef9969666def0cd1a000e121eaea580d4a313df4b37f32"}, 113 | ] 114 | 115 | [[package]] 116 | name = "isort" 117 | version = "5.10.1" 118 | description = "A Python utility / library to sort Python imports." 119 | optional = false 120 | python-versions = ">=3.6.1,<4.0" 121 | files = [ 122 | {file = "isort-5.10.1-py3-none-any.whl", hash = "sha256:6f62d78e2f89b4500b080fe3a81690850cd254227f27f75c3a0c491a1f351ba7"}, 123 | {file = "isort-5.10.1.tar.gz", hash = "sha256:e8443a5e7a020e9d7f97f1d7d9cd17c88bcb3bc7e218bf9cf5095fe550be2951"}, 124 | ] 125 | 126 | [package.extras] 127 | colors = ["colorama (>=0.4.3,<0.5.0)"] 128 | pipfile-deprecated-finder = ["pipreqs", "requirementslib"] 129 | plugins = ["setuptools"] 130 | requirements-deprecated-finder = ["pip-api", "pipreqs"] 131 | 132 | [[package]] 133 | name = "mypy-extensions" 134 | version = "0.4.3" 135 | description = "Experimental type system extensions for programs checked with the mypy typechecker." 136 | optional = false 137 | python-versions = "*" 138 | files = [ 139 | {file = "mypy_extensions-0.4.3-py2.py3-none-any.whl", hash = "sha256:090fedd75945a69ae91ce1303b5824f428daf5a028d2f6ab8a299250a846f15d"}, 140 | {file = "mypy_extensions-0.4.3.tar.gz", hash = "sha256:2d82818f5bb3e369420cb3c4060a7970edba416647068eb4c5343488a6c604a8"}, 141 | ] 142 | 143 | [[package]] 144 | name = "packaging" 145 | version = "24.0" 146 | description = "Core utilities for Python packages" 147 | optional = false 148 | python-versions = ">=3.7" 149 | files = [ 150 | {file = "packaging-24.0-py3-none-any.whl", hash = "sha256:2ddfb553fdf02fb784c234c7ba6ccc288296ceabec964ad2eae3777778130bc5"}, 151 | {file = "packaging-24.0.tar.gz", hash = "sha256:eb82c5e3e56209074766e6885bb04b8c38a0c015d0a30036ebe7ece34c9989e9"}, 152 | ] 153 | 154 | [[package]] 155 | name = "pathspec" 156 | version = "0.10.1" 157 | description = "Utility library for gitignore style pattern matching of file paths." 158 | optional = false 159 | python-versions = ">=3.7" 160 | files = [ 161 | {file = "pathspec-0.10.1-py3-none-any.whl", hash = "sha256:46846318467efc4556ccfd27816e004270a9eeeeb4d062ce5e6fc7a87c573f93"}, 162 | {file = "pathspec-0.10.1.tar.gz", hash = "sha256:7ace6161b621d31e7902eb6b5ae148d12cfd23f4a249b9ffb6b9fee12084323d"}, 163 | ] 164 | 165 | [[package]] 166 | name = "platformdirs" 167 | version = "2.5.2" 168 | description = "A small Python module for determining appropriate platform-specific dirs, e.g. a \"user data dir\"." 169 | optional = false 170 | python-versions = ">=3.7" 171 | files = [ 172 | {file = "platformdirs-2.5.2-py3-none-any.whl", hash = "sha256:027d8e83a2d7de06bbac4e5ef7e023c02b863d7ea5d079477e722bb41ab25788"}, 173 | {file = "platformdirs-2.5.2.tar.gz", hash = "sha256:58c8abb07dcb441e6ee4b11d8df0ac856038f944ab98b7be6b27b2a3c7feef19"}, 174 | ] 175 | 176 | [package.extras] 177 | docs = ["furo (>=2021.7.5b38)", "proselint (>=0.10.2)", "sphinx (>=4)", "sphinx-autodoc-typehints (>=1.12)"] 178 | test = ["appdirs (==1.4.4)", "pytest (>=6)", "pytest-cov (>=2.7)", "pytest-mock (>=3.6)"] 179 | 180 | [[package]] 181 | name = "pluggy" 182 | version = "1.0.0" 183 | description = "plugin and hook calling mechanisms for python" 184 | optional = false 185 | python-versions = ">=3.6" 186 | files = [ 187 | {file = "pluggy-1.0.0-py2.py3-none-any.whl", hash = "sha256:74134bbf457f031a36d68416e1509f34bd5ccc019f0bcc952c7b909d06b37bd3"}, 188 | {file = "pluggy-1.0.0.tar.gz", hash = "sha256:4224373bacce55f955a878bf9cfa763c1e360858e330072059e10bad68531159"}, 189 | ] 190 | 191 | [package.extras] 192 | dev = ["pre-commit", "tox"] 193 | testing = ["pytest", "pytest-benchmark"] 194 | 195 | [[package]] 196 | name = "py" 197 | version = "1.11.0" 198 | description = "library with cross-python path, ini-parsing, io, code, log facilities" 199 | optional = false 200 | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" 201 | files = [ 202 | {file = "py-1.11.0-py2.py3-none-any.whl", hash = "sha256:607c53218732647dff4acdfcd50cb62615cedf612e72d1724fb1a0cc6405b378"}, 203 | {file = "py-1.11.0.tar.gz", hash = "sha256:51c75c4126074b472f746a24399ad32f6053d1b34b68d2fa41e558e6f4a98719"}, 204 | ] 205 | 206 | [[package]] 207 | name = "pytest" 208 | version = "7.1.3" 209 | description = "pytest: simple powerful testing with Python" 210 | optional = false 211 | python-versions = ">=3.7" 212 | files = [ 213 | {file = "pytest-7.1.3-py3-none-any.whl", hash = "sha256:1377bda3466d70b55e3f5cecfa55bb7cfcf219c7964629b967c37cf0bda818b7"}, 214 | {file = "pytest-7.1.3.tar.gz", hash = "sha256:4f365fec2dff9c1162f834d9f18af1ba13062db0c708bf7b946f8a5c76180c39"}, 215 | ] 216 | 217 | [package.dependencies] 218 | attrs = ">=19.2.0" 219 | colorama = {version = "*", markers = "sys_platform == \"win32\""} 220 | iniconfig = "*" 221 | packaging = "*" 222 | pluggy = ">=0.12,<2.0" 223 | py = ">=1.8.2" 224 | tomli = ">=1.0.0" 225 | 226 | [package.extras] 227 | testing = ["argcomplete", "hypothesis (>=3.56)", "mock", "nose", "pygments (>=2.7.2)", "requests", "xmlschema"] 228 | 229 | [[package]] 230 | name = "tomli" 231 | version = "2.0.1" 232 | description = "A lil' TOML parser" 233 | optional = false 234 | python-versions = ">=3.7" 235 | files = [ 236 | {file = "tomli-2.0.1-py3-none-any.whl", hash = "sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc"}, 237 | {file = "tomli-2.0.1.tar.gz", hash = "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f"}, 238 | ] 239 | 240 | [[package]] 241 | name = "typing-extensions" 242 | version = "4.4.0" 243 | description = "Backported and Experimental Type Hints for Python 3.7+" 244 | optional = false 245 | python-versions = ">=3.7" 246 | files = [ 247 | {file = "typing_extensions-4.4.0-py3-none-any.whl", hash = "sha256:16fa4864408f655d35ec496218b85f79b3437c829e93320c7c9215ccfd92489e"}, 248 | {file = "typing_extensions-4.4.0.tar.gz", hash = "sha256:1511434bb92bf8dd198c12b1cc812e800d4181cfcb867674e0f8279cc93087aa"}, 249 | ] 250 | 251 | [metadata] 252 | lock-version = "2.0" 253 | python-versions = ">=3.8,<=3.11" 254 | content-hash = "58b361591134d140d126829a202ae79ca2b6d764432a94f13b2782e58f0b6984" 255 | -------------------------------------------------------------------------------- /pyproject.toml: -------------------------------------------------------------------------------- 1 | [tool.black] 2 | line-length = 100 3 | target-version = ['py39'] 4 | 5 | [tool.isort] 6 | combine_as_imports = true 7 | line_length = 100 8 | profile = "black" 9 | 10 | [tool.poetry] 11 | name = "docstring-generator" 12 | version = "0.3.4" 13 | description = "Auto generate docstring from type-hints." 14 | authors = ["FelixTheC "] 15 | readme = "README.md" 16 | license = "MIT" 17 | repository = "https://github.com/FelixTheC/docstring_generator" 18 | packages = [{include = "docstring_generator"}] 19 | classifiers=[ 20 | "Development Status :: 4 - Beta", 21 | "Environment :: Console", 22 | "License :: OSI Approved :: MIT License", 23 | "Programming Language :: Python :: 3", 24 | "Programming Language :: Python :: 3.9", 25 | "Programming Language :: Python :: 3.10", 26 | "Topic :: Utilities", 27 | "Topic :: Software Development :: Documentation", 28 | "Typing :: Typed", 29 | ] 30 | 31 | [tool.poetry.scripts] 32 | gendocs_new = "docstring_generator.new_gen_docs:main" 33 | 34 | [tool.poetry.dependencies] 35 | python = ">=3.8,<=3.11" 36 | click = "^8.1.3" 37 | docstring-generator-ext = ">=0.0.33" 38 | 39 | [tool.poetry.group.dev.dependencies] 40 | black = ">=22.8,<25.0" 41 | isort = "^5.10.1" 42 | pytest = "^7.1.3" 43 | 44 | [build-system] 45 | requires = ["poetry-core"] 46 | build-backend = "poetry.core.masonry.api" 47 | -------------------------------------------------------------------------------- /tests/tmp/__init__.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | """ 4 | @created: 01.10.22 5 | @author: felix 6 | """ 7 | -------------------------------------------------------------------------------- /tests/tmp/file_a_broken_after_second_iter.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | """ 4 | @created: 01.08.21 5 | @author: felix 6 | """ 7 | from typing import Dict, Literal, Union 8 | 9 | 10 | def foo( 11 | val_a: Literal["foo", "bar"], 12 | val_b: Dict[str, Union[int, float]], 13 | val_c: str = "Hello World", 14 | ) -> Dict[str, Union[int, float]]: 15 | """ 16 | Lorem ipsum dolor sit amet, consetetur sadipscing elitr, 17 | sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam 18 | 19 | 20 | Parameters 21 | ---------- 22 | val_a : argument of type `str` allowed values are `foo` or `bar` 23 | val_b : argument of type Dict(str, int or float) 24 | val_c : argument of type str 25 | Default is Hello World 26 | 27 | Returns 28 | ------- 29 | Dict(str, int or float) 30 | """ 31 | 32 | 33 | def bar(val_a: int, val_b: int) -> int: 34 | pass 35 | 36 | 37 | class Vehicle: 38 | """ 39 | The Vehicle object contains lots of vehicles 40 | 41 | 42 | Parameters 43 | ---------- 44 | arg : argument of type str 45 | args : variadic arguments of type tuple 46 | at least one value of type string is needed 47 | kwargs : variadic keyword arguments of type dict 48 | """ 49 | Function cars 50 | 51 | 52 | Parameters 53 | ---------- 54 | distance : argument of type float 55 | destination : argument of type str 56 | """ 57 | pass 58 | 59 | def fuel(self, fuel): 60 | """ 61 | Some text 62 | """ 63 | pass 64 | -------------------------------------------------------------------------------- /tests/tmp/file_a_one_iteration.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | """ 4 | @created: 01.08.21 5 | @author: felix 6 | """ 7 | from typing import Dict, Literal, Union 8 | 9 | 10 | def foo( 11 | val_a: Literal["foo", "bar"], 12 | val_b: Dict[str, Union[int, float]], 13 | val_c: str = "Hello World", 14 | ) -> Dict[str, Union[int, float]]: 15 | """ 16 | Lorem ipsum dolor sit amet, consetetur sadipscing elitr, 17 | sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam 18 | 19 | 20 | Parameters 21 | ---------- 22 | val_a : argument of type `str` allowed values are `foo` or `bar` 23 | val_b : argument of type Dict(str, int or float) 24 | val_c : argument of type str 25 | Default is Hello World 26 | 27 | Returns 28 | ------- 29 | Dict(str, int or float) 30 | """ 31 | 32 | 33 | def bar(val_a: int, val_b: int) -> int: 34 | pass 35 | 36 | 37 | class Vehicle: 38 | """ 39 | The Vehicle object contains lots of vehicles 40 | 41 | 42 | Parameters 43 | ---------- 44 | arg : argument of type str 45 | args : variadic arguments of type tuple 46 | kwargs : variadic keyword arguments of type dict 47 | """ -------------------------------------------------------------------------------- /tests/tmp/tmp.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | 4 | 5 | class Example: 6 | 7 | def some(self): 8 | pass 9 | --------------------------------------------------------------------------------