# -*- coding: utf-8 -*-
from setuptools import setup

package_dir = \
{'': 'src'}

packages = \
['click_inspect']

package_data = \
{'': ['*']}

install_requires = \
['Sphinx>=3.3.0,<4.0.0', 'click>=7.1.2,<8.0.0', 'typestring-parser>=0.1,<0.2']

extras_require = \
{':python_version < "3.8"': ['importlib_metadata>=1.6.1,<2.0.0'],
 ':python_version < "3.9"': ['typing-extensions>=3.7.4.3,<4.0.0.0']}

setup_kwargs = {
    'name': 'click-inspect',
    'version': '0.2',
    'description': 'Add options to click commands based on inspecting functions',
    'long_description': '[![Tests](https://github.com/Dominik1123/click-inspect/workflows/Tests/badge.svg)](https://github.com/Dominik1123/click-inspect/actions?workflow=Tests)\n[![Codecov](https://codecov.io/gh/Dominik1123/click-inspect/branch/main/graph/badge.svg)](https://codecov.io/gh/Dominik1123/click-inspect)\n[![PyPI](https://img.shields.io/pypi/v/click-inspect.svg)](https://pypi.org/project/click-inspect/)\n[![PyPI pyversions](https://img.shields.io/pypi/pyversions/click-inspect.svg?style=flat-square)](https://pypi.org/pypi/click-inspect/)\n\n# click-inspect\n\n*Add options to click commands based on inspecting functions*\n\n## Installation\n\n[`pip install click-inspect`](https://pypi.org/project/click-inspect/)\n\n## Usage\n\nSuppose an application containing an API function for which we would like to expose a command line interface. That function expects one or two arguments with internal data types and a bunch of configuration options. For example:\n\n```python\ndef display_data(data: List[Tuple[int, int]],\n                 *,\n                 size: int, symbol: str = \'x\', empty: str = \' \') -> str:\n    """Display the given data points in a 2D ASCII grid.\n\n    Args:\n        data (list of (int, int)): The data points as x- and y-tuples.\n        size (int): Size of the grid in both dimensions.\n        symbol (str): Symbol for displaying data points.\n        empty (str): Symbol for displaying empty space.\n\n    Returns:\n        str: The string containing the grid.\n    """\n    grid = [[empty]*size for _ in range(size)]\n    for x, y in data:\n        grid[y][x] = symbol\n    top = bottom = (\'+\', *\'-\'*size, \'+\')\n    grid = (top, *((\'|\', *row, \'|\') for row in grid), bottom)\n    return \'\\n\'.join(map(\'\'.join, grid))\n```\n\nHere the type of the first argument, ``data``, is an internal aspect of the application, but the remaining arguments are generic options.\n\nNow we want to create a [click](https://pypi.org/project/click/) interface for using this function from the command line. Specifically we want it to work on JSON files of the following format:\n\n```json\n{"data": [[1, 1], [2, 4], [3, 3]]}\n```\n\nSo the only thing our command needs to do is to read the JSON file and convert the content in a way that it is compatible with what `display_data` expects:\n\n```python\nimport json\nimport click\n\n\n@click.command()\n@click.argument(\'file\')\ndef display(file):\n    with open(file) as fh:\n        data = json.load(fh)[\'data\']\n    data = [[int(x) for x in row] for row in data]\n    print(display_data(data))\n\n\nif __name__ == \'__main__\':\n    display()\n```\n\nThen we can run the program in the following way:\n\n```text\n$ python example.py test.json\n+-----+\n|     |\n| x   |\n|     |\n|   x |\n|  x  |\n+-----+\n```\n\nNow this only uses the default configuration of the `display_data` function and we also want to expose these optional parameters to the command line interface. We can do so by adding a few options:\n\n```python\n@click.command()\n@click.argument(\'file\')\n@click.option(\'--size\', default=5, help=\'Size of the grid in both dimensions.\')\n@click.option(\'--symbol\', default=\'x\', help=\'Symbol for displaying data points.\')\n@click.option(\'--empty\', default=\' \', help=\'Symbol for displaying empty space.\')\ndef display(file, size, symbol, empty):\n    with open(file) as fh:\n        data = json.load(fh)[\'data\']\n    data = [[int(x) for x in row] for row in data]\n    print(display_data(data, size=size, symbol=symbol, empty=empty))\n```\n\nBut that\'s a lot of code duplication. We duplicated the parameter names, the default values and the help text from the docstring.\nAlso if we decide to add a new parameter to `display_data` we need to update the command as well.\n\nThis is where `click-inspect` comes in handy. Using the `add_options_from` decorator we can simply add all optional parameters from `display_data` to the `display` command without code duplication:\n\n```python\nfrom click_inspect import add_options_from\n\n@click.command()\n@click.argument(\'file\')\n@add_options_from(display_data)\ndef display(file, **kwargs):\n    with open(file) as fh:\n        data = json.load(fh)[\'data\']\n    data = [[int(x) for x in row] for row in data]\n    print(display_data(data, **kwargs))\n```\n\n### Customization\n\nThe `add_options_from` decorator supports various keyword parameters which can be used for\ncustomizing the way options are created from parameters. Please refer to the docstring\nof `add_options_from` for more information. In the following some possibilities are shown:\n\n```python\n# This adds only the `size` and `empty` parameters as options:\n@add_options_from(display_data, include={\'size\', \'empty\'})\n\n# This has a similar effect by excluding the `symbol` parameter:\n@add_options_from(display_data, exclude={\'symbol\'})\n\n# This specifies custom option-names for some of the parameters:\n@add_options_from(display_data, names={\'size\': [\'-s\', \'--size\'], \'empty\': [\'-e\', \'--empty\']})\n\n# This overrides the default value for the `symbol` parameter:\n@add_options_from(display_data, custom={\'symbol\': {\'default\': \'#\'}})\n```\n\n### Lists and tuples\n\n`click-inspect` also supports sequences as type hints (e.g. `list[int]` or `tuple[int, str]`).\nSpecifically those type hints are translated as follows:\n\n```python\nfoo: Sequence[int]\nfoo: List[int]\n# translates to\nclick.option(\'--foo\', multiple=True, type=int)\n\n# -------------------------------------------------- #\n\nfoo: Tuple[int, str]\n# translates to\nclick.option(\'--foo\', type=(int, str))\n```\n\nThese type hints are also supported as part of the docstring:\n\n```python\n"""\nArgs:\n    foo (list of int): Equivalent to List[int].\n    foo ((int, str)): Equivalent to Tuple[int, str].\n"""\n```\n\n### Unions\n\n`click-inspect` also supports `typing.Union` by simply selecting the first option as the type.\nSo `Union[int, str]` is equivalent to `int`.\nUnions are also supported as part of the docstring via `int or str`.\n\n## Docstring styles\n\n`click-inspect` supports inspecting [reST-style](https://www.python.org/dev/peps/pep-0287/) docstrings, as well as [Google-](https://google.github.io/styleguide/pyguide.html#38-comments-and-docstrings) and [Numpy-style](https://numpydoc.readthedocs.io/en/latest/format.html) docstrings via [`sphinx.ext.napoleon`](https://github.com/sphinx-doc/sphinx/tree/master/sphinx/ext/napoleon).\n',
    'author': 'Dominik1123',
    'author_email': None,
    'maintainer': None,
    'maintainer_email': None,
    'url': 'https://github.com/Dominik1123/click-inspect',
    'package_dir': package_dir,
    'packages': packages,
    'package_data': package_data,
    'install_requires': install_requires,
    'extras_require': extras_require,
    'python_requires': '>=3.7.9,<4.0.0',
}


setup(**setup_kwargs)
