Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package python-pick for openSUSE:Factory checked in at 2022-11-06 14:09:27 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/python-pick (Old) and /work/SRC/openSUSE:Factory/.python-pick.new.2275 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-pick" Sun Nov 6 14:09:27 2022 rev:7 rq:1033854 version:2.1.0 Changes: -------- --- /work/SRC/openSUSE:Factory/python-pick/python-pick.changes 2022-07-26 19:44:34.522405409 +0200 +++ /work/SRC/openSUSE:Factory/.python-pick.new.2275/python-pick.changes 2022-11-06 14:09:28.835729282 +0100 @@ -1,0 +2,32 @@ +Sun Nov 6 12:07:44 UTC 2022 - Luigi Baldoni <aloi...@gmx.com> + +- Update to version 2.1.0 + * Change the way scroll is handled. + version 2.0.2: + * Remove the additional space + version 2.0.1: + * Change multiselect symbols + * Bump pytest from 7.1.2 to 7.1.3 + version 2.0.0: + * Add Option class + * Drop options_map_func + * Drop register_custom_handler + * Remove docstrings + * Add multiselect example gif + * Use markdown for README + version 1.6.0: + * Update multiselect mode style + * Add multiselect example + * Fix examples + * Bump pytest from 6.2.5 to 7.1.2 + * Bump mypy from 0.961 to 0.971 + version 1.5.0: + * Fix mypy call in ci + * Create dependabot.yml + * Add static type checking to ci + * Check static type with pytest + * Format code + * Change list to sequence for Picker.options + * Rename all_selected to selected_indexes + +------------------------------------------------------------------- Old: ---- pick-1.4.0.tar.gz New: ---- pick-2.1.0.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ python-pick.spec ++++++ --- /var/tmp/diff_new_pack.WtJI1M/_old 2022-11-06 14:09:29.327732049 +0100 +++ /var/tmp/diff_new_pack.WtJI1M/_new 2022-11-06 14:09:29.331732071 +0100 @@ -17,7 +17,7 @@ Name: python-pick -Version: 1.4.0 +Version: 2.1.0 Release: 0 Summary: Curses-based interactive selection list module License: MIT @@ -53,7 +53,7 @@ %files %{python_files} %license LICENSE -%doc README.rst +%doc README.md %{python_sitelib}/* %changelog ++++++ pick-1.4.0.tar.gz -> pick-2.1.0.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pick-1.4.0/.github/dependabot.yml new/pick-2.1.0/.github/dependabot.yml --- old/pick-1.4.0/.github/dependabot.yml 1970-01-01 01:00:00.000000000 +0100 +++ new/pick-2.1.0/.github/dependabot.yml 2022-11-06 07:58:43.000000000 +0100 @@ -0,0 +1,11 @@ +# To get started with Dependabot version updates, you'll need to specify which +# package ecosystems to update and where the package manifests are located. +# Please see the documentation for all configuration options: +# https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates + +version: 2 +updates: + - package-ecosystem: "pip" # See documentation for possible values + directory: "/" # Location of package manifests + schedule: + interval: "daily" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pick-1.4.0/.github/workflows/ci.yml new/pick-2.1.0/.github/workflows/ci.yml --- old/pick-1.4.0/.github/workflows/ci.yml 2022-07-24 07:38:13.000000000 +0200 +++ new/pick-2.1.0/.github/workflows/ci.yml 2022-11-06 07:58:43.000000000 +0100 @@ -18,5 +18,8 @@ uses: abatilo/actions-poetry@v2.0.0 - name: Install dependencies run: poetry install + - name: Static type checking + run: poetry run mypy . + if: runner.os != 'Windows' - name: Run test run: poetry run pytest diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pick-1.4.0/README.md new/pick-2.1.0/README.md --- old/pick-1.4.0/README.md 1970-01-01 01:00:00.000000000 +0100 +++ new/pick-2.1.0/README.md 2022-11-06 07:58:43.000000000 +0100 @@ -0,0 +1,62 @@ +# pick + +[](https://github.com/wong2/pick/actions/workflows/ci.yml) +[](https://pypi.python.org/pypi/pick) +[](https://pypi.python.org/pypi/pick) + +**pick** is a small python library to help you create curses based +interactive selection list in the terminal. + +| Basic | Multiselect | +| :--------------------: | :--------------------------: | +|  |  | + +## Installation + + $ pip install pick + +## Usage + +**pick** comes with a simple api: + + >>> from pick import pick + + >>> title = 'Please choose your favorite programming language: ' + >>> options = ['Java', 'JavaScript', 'Python', 'PHP', 'C++', 'Erlang', 'Haskell'] + >>> option, index = pick(options, title) + >>> print(option) + >>> print(index) + +**outputs**: + + >>> C++ + >>> 4 + +**pick** multiselect example: + + >>> from pick import pick + + >>> title = 'Please choose your favorite programming language (press SPACE to mark, ENTER to continue): ' + >>> options = ['Java', 'JavaScript', 'Python', 'PHP', 'C++', 'Erlang', 'Haskell'] + >>> selected = pick(options, title, multiselect=True, min_selection_count=1) + >>> print(selected) + +**outputs**: + + >>> [('Java', 0), ('C++', 4)] + +## Options + +- `options`: a list of options to choose from +- `title`: (optional) a title above options list +- `indicator`: (optional) custom the selection indicator, defaults to `*` +- `default_index`: (optional) set this if the default selected option + is not the first one +- `multiselect`: (optional), if set to True its possible to select + multiple items by hitting SPACE +- `min_selection_count`: (optional) for multi select feature to + dictate a minimum of selected items before continuing + +## Community Projects + +[pickpack](https://github.com/anafvana/pickpack): A fork of `pick` to select tree data. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pick-1.4.0/README.rst new/pick-2.1.0/README.rst --- old/pick-1.4.0/README.rst 2022-07-24 07:38:13.000000000 +0200 +++ new/pick-2.1.0/README.rst 1970-01-01 01:00:00.000000000 +0100 @@ -1,123 +0,0 @@ -pick -==== - -.. image:: https://github.com/wong2/pick/actions/workflows/ci.yml/badge.svg - :target: https://github.com/wong2/pick/actions/workflows/ci.yml - -.. image:: https://img.shields.io/pypi/v/pick.svg - :alt: PyPI - :target: https://pypi.python.org/pypi/pick - -.. image:: https://img.shields.io/pypi/dm/pick - :alt: PyPI - :target: https://pypi.python.org/pypi/pick - -| - -**pick** is a small python library to help you create curses based interactive selection list in the terminal. - -.. image:: https://github.com/wong2/pick/raw/master/example/basic.gif - :alt: Demo - -Installation ------------- - -:: - - $ pip install pick - -Usage ------ - -**pick** comes with a simple api:: - - >>> from pick import pick - - >>> title = 'Please choose your favorite programming language: ' - >>> options = ['Java', 'JavaScript', 'Python', 'PHP', 'C++', 'Erlang', 'Haskell'] - >>> option, index = pick(options, title) - >>> print(option) - >>> print(index) - -**outputs**:: - - >>> C++ - >>> 4 - -**pick** multiselect example:: - - >>> from pick import pick - - >>> title = 'Please choose your favorite programming language (press SPACE to mark, ENTER to continue): ' - >>> options = ['Java', 'JavaScript', 'Python', 'PHP', 'C++', 'Erlang', 'Haskell'] - >>> selected = pick(options, title, multiselect=True, min_selection_count=1) - >>> print(selected) - -**outputs**:: - - >>> [('Java', 0), ('C++', 4)] - - -Options -------- - -* ``options``: a list of options to choose from -* ``title``: (optional) a title above options list -* ``indicator``: (optional) custom the selection indicator, defaults to * -* ``default_index``: (optional) set this if the default selected option is not the first one -* ``multiselect``: (optional), if set to True its possible to select multiple items by hitting SPACE -* ``min_selection_count``: (optional) for multi select feature to dictate a minimum of selected items before continuing -* ``options_map_func``: (optional) a mapping function to pass each option through before displaying - -Register custom handlers ------------------------- - -Sometimes you may need to register custom handlers for specific keyboard keys, you can use the ``register_custom_handler`` API:: - - >>> from pick import Picker - >>> title, options = 'Title', ['Option1', 'Option2'] - >>> picker = Picker(options, title) - >>> def go_back(picker): - ... return None, -1 - >>> picker.register_custom_handler(ord('h'), go_back) - >>> option, index = picker.start() - -* the custom handler will be called with the ``picker`` instance as it's parameter. -* the custom handler should either return a two element tuple, or None. -* if None is returned, the picker would continue to run, otherwise the picker will stop and return the tuple. - -Options Map Function --------------------- - -If your options are not in a format that you want displayed (such as a dictionary), you can pass in a mapping function which each option will be run through. The return value of the function will be displayed. - -* the selected option returned will be the original value and not the displayed return result from the ``options_map_func`` function. - -**pick** options map function example:: - - >>> from pick import pick - - >>> title = 'Please choose an option: ' - >>> options = [{'label': 'option1'}, {'label': 'option2'}, {'label': 'option3'}] - - >>> def get_label(option): return option.get('label') - - >>> selected = pick(options, title, indicator='*', options_map_func=get_label) - >>> print(selected) - -**displays**:: - - Please choose an option: - - * option1 - option2 - option3 - -**outputs**:: - - >>> ({ 'label': 'option1' }, 0) - -Community Projects --------------------- - -`pickpack <https://github.com/anafvana/pickpack>`_: A fork of `pick` to select tree data. Binary files old/pick-1.4.0/example/basic.gif and new/pick-2.1.0/example/basic.gif differ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pick-1.4.0/example/basic.py new/pick-2.1.0/example/basic.py --- old/pick-1.4.0/example/basic.py 2022-07-24 07:38:13.000000000 +0200 +++ new/pick-2.1.0/example/basic.py 2022-11-06 07:58:43.000000000 +0100 @@ -2,7 +2,5 @@ title = "Please choose your favorite programming language: " options = ["Java", "JavaScript", "Python", "PHP", "C++", "Erlang", "Haskell"] -selection = pick(options, title, indicator="=>", default_index=2) -assert len(selection) == 1 -option, index = selection[0] -print(option, index) +option, index = pick(options, title, indicator="=>", default_index=2) +print(f"You choosed {option} at index {index}") diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pick-1.4.0/example/custom.py new/pick-2.1.0/example/custom.py --- old/pick-1.4.0/example/custom.py 2022-07-24 07:38:13.000000000 +0200 +++ new/pick-2.1.0/example/custom.py 1970-01-01 01:00:00.000000000 +0100 @@ -1,32 +0,0 @@ -import curses -from pick import Picker -from typing import Tuple - - -def print_selection(selection): - if isinstance(selection, list): - assert len(selection) == 1 - option, index = selection[0] - print(option, index) - else: - print("KEY_LEFT pressed!") - - -def go_back(picker): - return (None, -1) - - -title = "Please choose your favorite programming language: " -options = ["Java", "JavaScript", "Python", "PHP", "C++", "Erlang", "Haskell"] - -# with type annotation -picker: Picker[Tuple[None, int], str] = Picker(options, title) -picker.register_custom_handler(curses.KEY_LEFT, go_back) -selection = picker.start() -print_selection(selection) - -# with type warning suppression -unannotated_picker = Picker(options, title) # type: ignore[var-annotated] -unannotated_picker.register_custom_handler(curses.KEY_LEFT, go_back) -selection = picker.start() -print_selection(selection) Binary files old/pick-1.4.0/example/multiselect.gif and new/pick-2.1.0/example/multiselect.gif differ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pick-1.4.0/example/multiselect.py new/pick-2.1.0/example/multiselect.py --- old/pick-1.4.0/example/multiselect.py 1970-01-01 01:00:00.000000000 +0100 +++ new/pick-2.1.0/example/multiselect.py 2022-11-06 07:58:43.000000000 +0100 @@ -0,0 +1,6 @@ +from pick import pick + +title = "Choose your favorite programming language(use space to select)" +options = ["Java", "JavaScript", "Python", "PHP", "C++", "Erlang", "Haskell"] +selected = pick(options, title, multiselect=True, min_selection_count=1) +print(selected) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pick-1.4.0/example/option.py new/pick-2.1.0/example/option.py --- old/pick-1.4.0/example/option.py 1970-01-01 01:00:00.000000000 +0100 +++ new/pick-2.1.0/example/option.py 2022-11-06 07:58:43.000000000 +0100 @@ -0,0 +1,10 @@ +from pick import pick, Option + +title = "Please choose your favorite programming language: " +options = [ + Option("Java", ".java"), + Option("Python", ".py"), + Option("JavaScript", ".js"), +] +option, index = pick(options, title) +print(f"You choosed {option} at index {index}") diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pick-1.4.0/example/options_map_func.py new/pick-2.1.0/example/options_map_func.py --- old/pick-1.4.0/example/options_map_func.py 2022-07-24 07:38:13.000000000 +0200 +++ new/pick-2.1.0/example/options_map_func.py 1970-01-01 01:00:00.000000000 +0100 @@ -1,22 +0,0 @@ -from pick import pick - -title = "Please choose your favorite fruit: " -options = [ - {"name": "Apples", "grow_on": "trees"}, - {"name": "Oranges", "grow_on": "trees"}, - {"name": "Strawberries", "grow_on": "vines"}, - {"name": "Grapes", "grow_on": "vines"}, -] - - -def get_description_for_display(option): - # format the option data for display - return "{0} (grow on {1})".format(option.get("name"), option.get("grow_on")) - - -selection = pick( - options, title, indicator="=>", options_map_func=get_description_for_display -) -assert len(selection) == 1 -option, index = selection[0] -print(option, index) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pick-1.4.0/example/scroll.py new/pick-2.1.0/example/scroll.py --- old/pick-1.4.0/example/scroll.py 2022-07-24 07:38:13.000000000 +0200 +++ new/pick-2.1.0/example/scroll.py 2022-11-06 07:58:43.000000000 +0100 @@ -2,7 +2,5 @@ title = "Select:" options = ["foo.bar%s.baz" % x for x in range(1, 71)] -selection = pick(options, title) -assert len(selection) == 1 -option, index = selection[0] +option, index = pick(options, title) print(option, index) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pick-1.4.0/poetry.lock new/pick-2.1.0/poetry.lock --- old/pick-1.4.0/poetry.lock 2022-07-24 07:38:13.000000000 +0200 +++ new/pick-2.1.0/poetry.lock 2022-11-06 07:58:43.000000000 +0100 @@ -1,12 +1,4 @@ [[package]] -name = "atomicwrites" -version = "1.4.1" -description = "Atomic file writes." -category = "dev" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" - -[[package]] name = "attrs" version = "21.4.0" description = "Classes Without Boilerplate" @@ -15,10 +7,10 @@ python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" [package.extras] -dev = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "mypy", "pytest-mypy-plugins", "zope.interface", "furo", "sphinx", "sphinx-notfound-page", "pre-commit", "cloudpickle"] -docs = ["furo", "sphinx", "zope.interface", "sphinx-notfound-page"] -tests = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "mypy", "pytest-mypy-plugins", "zope.interface", "cloudpickle"] -tests_no_zope = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "mypy", "pytest-mypy-plugins", "cloudpickle"] +dev = ["cloudpickle", "coverage[toml] (>=5.0.2)", "furo", "hypothesis", "mypy", "pre-commit", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "six", "sphinx", "sphinx-notfound-page", "zope.interface"] +docs = ["furo", "sphinx", "sphinx-notfound-page", "zope.interface"] +tests = ["cloudpickle", "coverage[toml] (>=5.0.2)", "hypothesis", "mypy", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "six", "zope.interface"] +tests_no_zope = ["cloudpickle", "coverage[toml] (>=5.0.2)", "hypothesis", "mypy", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "six"] [[package]] name = "cfgv" @@ -80,9 +72,9 @@ zipp = ">=0.5" [package.extras] -docs = ["sphinx", "jaraco.packaging (>=8.2)", "rst.linker (>=1.9)"] +docs = ["jaraco.packaging (>=8.2)", "rst.linker (>=1.9)", "sphinx"] perf = ["ipython"] -testing = ["pytest (>=6)", "pytest-checkdocs (>=2.4)", "pytest-flake8", "pytest-cov", "pytest-enabler (>=1.0.1)", "packaging", "pep517", "pyfakefs", "flufl.flake8", "pytest-perf (>=0.9.2)", "pytest-black (>=0.3.7)", "pytest-mypy", "importlib-resources (>=1.3)"] +testing = ["flufl.flake8", "importlib-resources (>=1.3)", "packaging", "pep517", "pyfakefs", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=1.0.1)", "pytest-flake8", "pytest-mypy", "pytest-perf (>=0.9.2)"] [[package]] name = "iniconfig" @@ -94,7 +86,7 @@ [[package]] name = "mypy" -version = "0.961" +version = "0.971" description = "Optional static typing for Python" category = "dev" optional = false @@ -147,8 +139,8 @@ python-versions = ">=3.7" [package.extras] -docs = ["furo (>=2021.7.5b38)", "proselint (>=0.10.2)", "sphinx-autodoc-typehints (>=1.12)", "sphinx (>=4)"] -test = ["appdirs (==1.4.4)", "pytest-cov (>=2.7)", "pytest-mock (>=3.6)", "pytest (>=6)"] +docs = ["furo (>=2021.7.5b38)", "proselint (>=0.10.2)", "sphinx (>=4)", "sphinx-autodoc-typehints (>=1.12)"] +test = ["appdirs (==1.4.4)", "pytest (>=6)", "pytest-cov (>=2.7)", "pytest-mock (>=3.6)"] [[package]] name = "pluggy" @@ -203,14 +195,13 @@ [[package]] name = "pytest" -version = "6.2.5" +version = "7.1.3" description = "pytest: simple powerful testing with Python" category = "dev" optional = false -python-versions = ">=3.6" +python-versions = ">=3.7" [package.dependencies] -atomicwrites = {version = ">=1.0", markers = "sys_platform == \"win32\""} attrs = ">=19.2.0" colorama = {version = "*", markers = "sys_platform == \"win32\""} importlib-metadata = {version = ">=0.12", markers = "python_version < \"3.8\""} @@ -218,10 +209,10 @@ packaging = "*" pluggy = ">=0.12,<2.0" py = ">=1.8.2" -toml = "*" +tomli = ">=1.0.0" [package.extras] -testing = ["argcomplete", "hypothesis (>=3.56)", "mock", "nose", "requests", "xmlschema"] +testing = ["argcomplete", "hypothesis (>=3.56)", "mock", "nose", "pygments (>=2.7.2)", "requests", "xmlschema"] [[package]] name = "pyyaml" @@ -288,7 +279,7 @@ [package.extras] docs = ["proselint (>=0.10.2)", "sphinx (>=3)", "sphinx-argparse (>=0.2.5)", "sphinx-rtd-theme (>=0.4.3)", "towncrier (>=21.3)"] -testing = ["coverage (>=4)", "coverage-enable-subprocess (>=1)", "flaky (>=3)", "pytest (>=4)", "pytest-env (>=0.6.2)", "pytest-freezegun (>=0.4.1)", "pytest-mock (>=2)", "pytest-randomly (>=1)", "pytest-timeout (>=1)", "packaging (>=20.0)"] +testing = ["coverage (>=4)", "coverage-enable-subprocess (>=1)", "flaky (>=3)", "packaging (>=20.0)", "pytest (>=4)", "pytest-env (>=0.6.2)", "pytest-freezegun (>=0.4.1)", "pytest-mock (>=2)", "pytest-randomly (>=1)", "pytest-timeout (>=1)"] [[package]] name = "windows-curses" @@ -307,40 +298,202 @@ python-versions = ">=3.6" [package.extras] -docs = ["sphinx", "jaraco.packaging (>=8.2)", "rst.linker (>=1.9)"] -testing = ["pytest (>=4.6)", "pytest-checkdocs (>=2.4)", "pytest-flake8", "pytest-cov", "pytest-enabler (>=1.0.1)", "jaraco.itertools", "func-timeout", "pytest-black (>=0.3.7)", "pytest-mypy"] +docs = ["jaraco.packaging (>=8.2)", "rst.linker (>=1.9)", "sphinx"] +testing = ["func-timeout", "jaraco.itertools", "pytest (>=4.6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=1.0.1)", "pytest-flake8", "pytest-mypy"] [metadata] lock-version = "1.1" python-versions = ">=3.7" -content-hash = "e568d233095e1d85550e7047fd32b8a47bb52bfcc8b1beb1d7145c35ccd82bbd" +content-hash = "8ad036630d1feeddb525fbba98a26da3a718f58357b1c6b9fcf6dac57ef6c353" [metadata.files] -atomicwrites = [] -attrs = [] -cfgv = [] -colorama = [] -distlib = [] -filelock = [] -identify = [] -importlib-metadata = [] -iniconfig = [] -mypy = [] -mypy-extensions = [] -nodeenv = [] -packaging = [] -platformdirs = [] -pluggy = [] -pre-commit = [] -py = [] -pyparsing = [] -pytest = [] -pyyaml = [] -six = [] -toml = [] -tomli = [] -typed-ast = [] -typing-extensions = [] -virtualenv = [] -windows-curses = [] -zipp = [] +attrs = [ + {file = "attrs-21.4.0-py2.py3-none-any.whl", hash = "sha256:2d27e3784d7a565d36ab851fe94887c5eccd6a463168875832a1be79c82828b4"}, + {file = "attrs-21.4.0.tar.gz", hash = "sha256:626ba8234211db98e869df76230a137c4c40a12d72445c45d5f5b716f076e2fd"}, +] +cfgv = [ + {file = "cfgv-3.3.1-py2.py3-none-any.whl", hash = "sha256:c6a0883f3917a037485059700b9e75da2464e6c27051014ad85ba6aaa5884426"}, + {file = "cfgv-3.3.1.tar.gz", hash = "sha256:f5a830efb9ce7a445376bb66ec94c638a9787422f96264c98edc6bdeed8ab736"}, +] +colorama = [ + {file = "colorama-0.4.5-py2.py3-none-any.whl", hash = "sha256:854bf444933e37f5824ae7bfc1e98d5bce2ebe4160d46b5edf346a89358e99da"}, + {file = "colorama-0.4.5.tar.gz", hash = "sha256:e6c6b4334fc50988a639d9b98aa429a0b57da6e17b9a44f0451f930b6967b7a4"}, +] +distlib = [ + {file = "distlib-0.3.5-py2.py3-none-any.whl", hash = "sha256:b710088c59f06338ca514800ad795a132da19fda270e3ce4affc74abf955a26c"}, + {file = "distlib-0.3.5.tar.gz", hash = "sha256:a7f75737c70be3b25e2bee06288cec4e4c221de18455b2dd037fe2a795cab2fe"}, +] +filelock = [ + {file = "filelock-3.7.1-py3-none-any.whl", hash = "sha256:37def7b658813cda163b56fc564cdc75e86d338246458c4c28ae84cabefa2404"}, + {file = "filelock-3.7.1.tar.gz", hash = "sha256:3a0fd85166ad9dbab54c9aec96737b744106dc5f15c0b09a6744a445299fcf04"}, +] +identify = [ + {file = "identify-2.5.2-py2.py3-none-any.whl", hash = "sha256:feaa9db2dc0ce333b453ce171c0cf1247bbfde2c55fc6bb785022d411a1b78b5"}, + {file = "identify-2.5.2.tar.gz", hash = "sha256:a3d4c096b384d50d5e6dc5bc8b9bc44f1f61cefebd750a7b3e9f939b53fb214d"}, +] +importlib-metadata = [ + {file = "importlib_metadata-4.8.3-py3-none-any.whl", hash = "sha256:65a9576a5b2d58ca44d133c42a241905cc45e34d2c06fd5ba2bafa221e5d7b5e"}, + {file = "importlib_metadata-4.8.3.tar.gz", hash = "sha256:766abffff765960fcc18003801f7044eb6755ffae4521c8e8ce8e83b9c9b0668"}, +] +iniconfig = [ + {file = "iniconfig-1.1.1-py2.py3-none-any.whl", hash = "sha256:011e24c64b7f47f6ebd835bb12a743f2fbe9a26d4cecaa7f53bc4f35ee9da8b3"}, + {file = "iniconfig-1.1.1.tar.gz", hash = "sha256:bc3af051d7d14b2ee5ef9969666def0cd1a000e121eaea580d4a313df4b37f32"}, +] +mypy = [ + {file = "mypy-0.971-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:f2899a3cbd394da157194f913a931edfd4be5f274a88041c9dc2d9cdcb1c315c"}, + {file = "mypy-0.971-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:98e02d56ebe93981c41211c05adb630d1d26c14195d04d95e49cd97dbc046dc5"}, + {file = "mypy-0.971-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:19830b7dba7d5356d3e26e2427a2ec91c994cd92d983142cbd025ebe81d69cf3"}, + {file = "mypy-0.971-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:02ef476f6dcb86e6f502ae39a16b93285fef97e7f1ff22932b657d1ef1f28655"}, + {file = "mypy-0.971-cp310-cp310-win_amd64.whl", hash = "sha256:25c5750ba5609a0c7550b73a33deb314ecfb559c350bb050b655505e8aed4103"}, + {file = "mypy-0.971-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:d3348e7eb2eea2472db611486846742d5d52d1290576de99d59edeb7cd4a42ca"}, + {file = "mypy-0.971-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:3fa7a477b9900be9b7dd4bab30a12759e5abe9586574ceb944bc29cddf8f0417"}, + {file = "mypy-0.971-cp36-cp36m-win_amd64.whl", hash = "sha256:2ad53cf9c3adc43cf3bea0a7d01a2f2e86db9fe7596dfecb4496a5dda63cbb09"}, + {file = "mypy-0.971-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:855048b6feb6dfe09d3353466004490b1872887150c5bb5caad7838b57328cc8"}, + {file = "mypy-0.971-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:23488a14a83bca6e54402c2e6435467a4138785df93ec85aeff64c6170077fb0"}, + {file = "mypy-0.971-cp37-cp37m-win_amd64.whl", hash = "sha256:4b21e5b1a70dfb972490035128f305c39bc4bc253f34e96a4adf9127cf943eb2"}, + {file = "mypy-0.971-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:9796a2ba7b4b538649caa5cecd398d873f4022ed2333ffde58eaf604c4d2cb27"}, + {file = "mypy-0.971-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:5a361d92635ad4ada1b1b2d3630fc2f53f2127d51cf2def9db83cba32e47c856"}, + {file = "mypy-0.971-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:b793b899f7cf563b1e7044a5c97361196b938e92f0a4343a5d27966a53d2ec71"}, + {file = "mypy-0.971-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:d1ea5d12c8e2d266b5fb8c7a5d2e9c0219fedfeb493b7ed60cd350322384ac27"}, + {file = "mypy-0.971-cp38-cp38-win_amd64.whl", hash = "sha256:23c7ff43fff4b0df93a186581885c8512bc50fc4d4910e0f838e35d6bb6b5e58"}, + {file = "mypy-0.971-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:1f7656b69974a6933e987ee8ffb951d836272d6c0f81d727f1d0e2696074d9e6"}, + {file = "mypy-0.971-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:d2022bfadb7a5c2ef410d6a7c9763188afdb7f3533f22a0a32be10d571ee4bbe"}, + {file = "mypy-0.971-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:ef943c72a786b0f8d90fd76e9b39ce81fb7171172daf84bf43eaf937e9f220a9"}, + {file = "mypy-0.971-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:d744f72eb39f69312bc6c2abf8ff6656973120e2eb3f3ec4f758ed47e414a4bf"}, + {file = "mypy-0.971-cp39-cp39-win_amd64.whl", hash = "sha256:77a514ea15d3007d33a9e2157b0ba9c267496acf12a7f2b9b9f8446337aac5b0"}, + {file = "mypy-0.971-py3-none-any.whl", hash = "sha256:0d054ef16b071149917085f51f89555a576e2618d5d9dd70bd6eea6410af3ac9"}, + {file = "mypy-0.971.tar.gz", hash = "sha256:40b0f21484238269ae6a57200c807d80debc6459d444c0489a102d7c6a75fa56"}, +] +mypy-extensions = [ + {file = "mypy_extensions-0.4.3-py2.py3-none-any.whl", hash = "sha256:090fedd75945a69ae91ce1303b5824f428daf5a028d2f6ab8a299250a846f15d"}, + {file = "mypy_extensions-0.4.3.tar.gz", hash = "sha256:2d82818f5bb3e369420cb3c4060a7970edba416647068eb4c5343488a6c604a8"}, +] +nodeenv = [ + {file = "nodeenv-1.7.0-py2.py3-none-any.whl", hash = "sha256:27083a7b96a25f2f5e1d8cb4b6317ee8aeda3bdd121394e5ac54e498028a042e"}, + {file = "nodeenv-1.7.0.tar.gz", hash = "sha256:e0e7f7dfb85fc5394c6fe1e8fa98131a2473e04311a45afb6508f7cf1836fa2b"}, +] +packaging = [ + {file = "packaging-21.3-py3-none-any.whl", hash = "sha256:ef103e05f519cdc783ae24ea4e2e0f508a9c99b2d4969652eed6a2e1ea5bd522"}, + {file = "packaging-21.3.tar.gz", hash = "sha256:dd47c42927d89ab911e606518907cc2d3a1f38bbd026385970643f9c5b8ecfeb"}, +] +platformdirs = [ + {file = "platformdirs-2.5.2-py3-none-any.whl", hash = "sha256:027d8e83a2d7de06bbac4e5ef7e023c02b863d7ea5d079477e722bb41ab25788"}, + {file = "platformdirs-2.5.2.tar.gz", hash = "sha256:58c8abb07dcb441e6ee4b11d8df0ac856038f944ab98b7be6b27b2a3c7feef19"}, +] +pluggy = [ + {file = "pluggy-1.0.0-py2.py3-none-any.whl", hash = "sha256:74134bbf457f031a36d68416e1509f34bd5ccc019f0bcc952c7b909d06b37bd3"}, + {file = "pluggy-1.0.0.tar.gz", hash = "sha256:4224373bacce55f955a878bf9cfa763c1e360858e330072059e10bad68531159"}, +] +pre-commit = [ + {file = "pre_commit-2.20.0-py2.py3-none-any.whl", hash = "sha256:51a5ba7c480ae8072ecdb6933df22d2f812dc897d5fe848778116129a681aac7"}, + {file = "pre_commit-2.20.0.tar.gz", hash = "sha256:a978dac7bc9ec0bcee55c18a277d553b0f419d259dadb4b9418ff2d00eb43959"}, +] +py = [ + {file = "py-1.11.0-py2.py3-none-any.whl", hash = "sha256:607c53218732647dff4acdfcd50cb62615cedf612e72d1724fb1a0cc6405b378"}, + {file = "py-1.11.0.tar.gz", hash = "sha256:51c75c4126074b472f746a24399ad32f6053d1b34b68d2fa41e558e6f4a98719"}, +] +pyparsing = [ + {file = "pyparsing-3.0.7-py3-none-any.whl", hash = "sha256:a6c06a88f252e6c322f65faf8f418b16213b51bdfaece0524c1c1bc30c63c484"}, + {file = "pyparsing-3.0.7.tar.gz", hash = "sha256:18ee9022775d270c55187733956460083db60b37d0d0fb357445f3094eed3eea"}, +] +pytest = [ + {file = "pytest-7.1.3-py3-none-any.whl", hash = "sha256:1377bda3466d70b55e3f5cecfa55bb7cfcf219c7964629b967c37cf0bda818b7"}, + {file = "pytest-7.1.3.tar.gz", hash = "sha256:4f365fec2dff9c1162f834d9f18af1ba13062db0c708bf7b946f8a5c76180c39"}, +] +pyyaml = [ + {file = "PyYAML-6.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d4db7c7aef085872ef65a8fd7d6d09a14ae91f691dec3e87ee5ee0539d516f53"}, + {file = "PyYAML-6.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9df7ed3b3d2e0ecfe09e14741b857df43adb5a3ddadc919a2d94fbdf78fea53c"}, + {file = "PyYAML-6.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:77f396e6ef4c73fdc33a9157446466f1cff553d979bd00ecb64385760c6babdc"}, + {file = "PyYAML-6.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a80a78046a72361de73f8f395f1f1e49f956c6be882eed58505a15f3e430962b"}, + {file = "PyYAML-6.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:f84fbc98b019fef2ee9a1cb3ce93e3187a6df0b2538a651bfb890254ba9f90b5"}, + {file = "PyYAML-6.0-cp310-cp310-win32.whl", hash = "sha256:2cd5df3de48857ed0544b34e2d40e9fac445930039f3cfe4bcc592a1f836d513"}, + {file = "PyYAML-6.0-cp310-cp310-win_amd64.whl", hash = "sha256:daf496c58a8c52083df09b80c860005194014c3698698d1a57cbcfa182142a3a"}, + {file = "PyYAML-6.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:897b80890765f037df3403d22bab41627ca8811ae55e9a722fd0392850ec4d86"}, + {file = "PyYAML-6.0-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:50602afada6d6cbfad699b0c7bb50d5ccffa7e46a3d738092afddc1f9758427f"}, + {file = "PyYAML-6.0-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:48c346915c114f5fdb3ead70312bd042a953a8ce5c7106d5bfb1a5254e47da92"}, + {file = "PyYAML-6.0-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:98c4d36e99714e55cfbaaee6dd5badbc9a1ec339ebfc3b1f52e293aee6bb71a4"}, + {file = "PyYAML-6.0-cp36-cp36m-win32.whl", hash = "sha256:0283c35a6a9fbf047493e3a0ce8d79ef5030852c51e9d911a27badfde0605293"}, + {file = "PyYAML-6.0-cp36-cp36m-win_amd64.whl", hash = "sha256:07751360502caac1c067a8132d150cf3d61339af5691fe9e87803040dbc5db57"}, + {file = "PyYAML-6.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:819b3830a1543db06c4d4b865e70ded25be52a2e0631ccd2f6a47a2822f2fd7c"}, + {file = "PyYAML-6.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:473f9edb243cb1935ab5a084eb238d842fb8f404ed2193a915d1784b5a6b5fc0"}, + {file = "PyYAML-6.0-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0ce82d761c532fe4ec3f87fc45688bdd3a4c1dc5e0b4a19814b9009a29baefd4"}, + {file = "PyYAML-6.0-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:231710d57adfd809ef5d34183b8ed1eeae3f76459c18fb4a0b373ad56bedcdd9"}, + {file = "PyYAML-6.0-cp37-cp37m-win32.whl", hash = "sha256:c5687b8d43cf58545ade1fe3e055f70eac7a5a1a0bf42824308d868289a95737"}, + {file = "PyYAML-6.0-cp37-cp37m-win_amd64.whl", hash = "sha256:d15a181d1ecd0d4270dc32edb46f7cb7733c7c508857278d3d378d14d606db2d"}, + {file = "PyYAML-6.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:0b4624f379dab24d3725ffde76559cff63d9ec94e1736b556dacdfebe5ab6d4b"}, + {file = "PyYAML-6.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:213c60cd50106436cc818accf5baa1aba61c0189ff610f64f4a3e8c6726218ba"}, + {file = "PyYAML-6.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9fa600030013c4de8165339db93d182b9431076eb98eb40ee068700c9c813e34"}, + {file = "PyYAML-6.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:277a0ef2981ca40581a47093e9e2d13b3f1fbbeffae064c1d21bfceba2030287"}, + {file = "PyYAML-6.0-cp38-cp38-win32.whl", hash = "sha256:d4eccecf9adf6fbcc6861a38015c2a64f38b9d94838ac1810a9023a0609e1b78"}, + {file = "PyYAML-6.0-cp38-cp38-win_amd64.whl", hash = "sha256:1e4747bc279b4f613a09eb64bba2ba602d8a6664c6ce6396a4d0cd413a50ce07"}, + {file = "PyYAML-6.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:055d937d65826939cb044fc8c9b08889e8c743fdc6a32b33e2390f66013e449b"}, + {file = "PyYAML-6.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:e61ceaab6f49fb8bdfaa0f92c4b57bcfbea54c09277b1b4f7ac376bfb7a7c174"}, + {file = "PyYAML-6.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d67d839ede4ed1b28a4e8909735fc992a923cdb84e618544973d7dfc71540803"}, + {file = "PyYAML-6.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cba8c411ef271aa037d7357a2bc8f9ee8b58b9965831d9e51baf703280dc73d3"}, + {file = "PyYAML-6.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:40527857252b61eacd1d9af500c3337ba8deb8fc298940291486c465c8b46ec0"}, + {file = "PyYAML-6.0-cp39-cp39-win32.whl", hash = "sha256:b5b9eccad747aabaaffbc6064800670f0c297e52c12754eb1d976c57e4f74dcb"}, + {file = "PyYAML-6.0-cp39-cp39-win_amd64.whl", hash = "sha256:b3d267842bf12586ba6c734f89d1f5b871df0273157918b0ccefa29deb05c21c"}, + {file = "PyYAML-6.0.tar.gz", hash = "sha256:68fb519c14306fec9720a2a5b45bc9f0c8d1b9c72adf45c37baedfcd949c35a2"}, +] +six = [ + {file = "six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"}, + {file = "six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926"}, +] +toml = [ + {file = "toml-0.10.2-py2.py3-none-any.whl", hash = "sha256:806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b"}, + {file = "toml-0.10.2.tar.gz", hash = "sha256:b3bda1d108d5dd99f4a20d24d9c348e91c4db7ab1b749200bded2f839ccbe68f"}, +] +tomli = [ + {file = "tomli-1.2.3-py3-none-any.whl", hash = "sha256:e3069e4be3ead9668e21cb9b074cd948f7b3113fd9c8bba083f48247aab8b11c"}, + {file = "tomli-1.2.3.tar.gz", hash = "sha256:05b6166bff487dc068d322585c7ea4ef78deed501cc124060e0f238e89a9231f"}, +] +typed-ast = [ + {file = "typed_ast-1.5.4-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:669dd0c4167f6f2cd9f57041e03c3c2ebf9063d0757dc89f79ba1daa2bfca9d4"}, + {file = "typed_ast-1.5.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:211260621ab1cd7324e0798d6be953d00b74e0428382991adfddb352252f1d62"}, + {file = "typed_ast-1.5.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:267e3f78697a6c00c689c03db4876dd1efdfea2f251a5ad6555e82a26847b4ac"}, + {file = "typed_ast-1.5.4-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:c542eeda69212fa10a7ada75e668876fdec5f856cd3d06829e6aa64ad17c8dfe"}, + {file = "typed_ast-1.5.4-cp310-cp310-win_amd64.whl", hash = "sha256:a9916d2bb8865f973824fb47436fa45e1ebf2efd920f2b9f99342cb7fab93f72"}, + {file = "typed_ast-1.5.4-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:79b1e0869db7c830ba6a981d58711c88b6677506e648496b1f64ac7d15633aec"}, + {file = "typed_ast-1.5.4-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a94d55d142c9265f4ea46fab70977a1944ecae359ae867397757d836ea5a3f47"}, + {file = "typed_ast-1.5.4-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:183afdf0ec5b1b211724dfef3d2cad2d767cbefac291f24d69b00546c1837fb6"}, + {file = "typed_ast-1.5.4-cp36-cp36m-win_amd64.whl", hash = "sha256:639c5f0b21776605dd6c9dbe592d5228f021404dafd377e2b7ac046b0349b1a1"}, + {file = "typed_ast-1.5.4-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:cf4afcfac006ece570e32d6fa90ab74a17245b83dfd6655a6f68568098345ff6"}, + {file = "typed_ast-1.5.4-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ed855bbe3eb3715fca349c80174cfcfd699c2f9de574d40527b8429acae23a66"}, + {file = "typed_ast-1.5.4-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:6778e1b2f81dfc7bc58e4b259363b83d2e509a65198e85d5700dfae4c6c8ff1c"}, + {file = "typed_ast-1.5.4-cp37-cp37m-win_amd64.whl", hash = "sha256:0261195c2062caf107831e92a76764c81227dae162c4f75192c0d489faf751a2"}, + {file = "typed_ast-1.5.4-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:2efae9db7a8c05ad5547d522e7dbe62c83d838d3906a3716d1478b6c1d61388d"}, + {file = "typed_ast-1.5.4-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:7d5d014b7daa8b0bf2eaef684295acae12b036d79f54178b92a2b6a56f92278f"}, + {file = "typed_ast-1.5.4-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:370788a63915e82fd6f212865a596a0fefcbb7d408bbbb13dea723d971ed8bdc"}, + {file = "typed_ast-1.5.4-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:4e964b4ff86550a7a7d56345c7864b18f403f5bd7380edf44a3c1fb4ee7ac6c6"}, + {file = "typed_ast-1.5.4-cp38-cp38-win_amd64.whl", hash = "sha256:683407d92dc953c8a7347119596f0b0e6c55eb98ebebd9b23437501b28dcbb8e"}, + {file = "typed_ast-1.5.4-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:4879da6c9b73443f97e731b617184a596ac1235fe91f98d279a7af36c796da35"}, + {file = "typed_ast-1.5.4-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:3e123d878ba170397916557d31c8f589951e353cc95fb7f24f6bb69adc1a8a97"}, + {file = "typed_ast-1.5.4-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ebd9d7f80ccf7a82ac5f88c521115cc55d84e35bf8b446fcd7836eb6b98929a3"}, + {file = "typed_ast-1.5.4-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:98f80dee3c03455e92796b58b98ff6ca0b2a6f652120c263efdba4d6c5e58f72"}, + {file = "typed_ast-1.5.4-cp39-cp39-win_amd64.whl", hash = "sha256:0fdbcf2fef0ca421a3f5912555804296f0b0960f0418c440f5d6d3abb549f3e1"}, + {file = "typed_ast-1.5.4.tar.gz", hash = "sha256:39e21ceb7388e4bb37f4c679d72707ed46c2fbf2a5609b8b8ebc4b067d977df2"}, +] +typing-extensions = [ + {file = "typing_extensions-4.1.1-py3-none-any.whl", hash = "sha256:21c85e0fe4b9a155d0799430b0ad741cdce7e359660ccbd8b530613e8df88ce2"}, + {file = "typing_extensions-4.1.1.tar.gz", hash = "sha256:1a9462dcc3347a79b1f1c0271fbe79e844580bb598bafa1ed208b94da3cdcd42"}, +] +virtualenv = [ + {file = "virtualenv-20.15.1-py2.py3-none-any.whl", hash = "sha256:b30aefac647e86af6d82bfc944c556f8f1a9c90427b2fb4e3bfbf338cb82becf"}, + {file = "virtualenv-20.15.1.tar.gz", hash = "sha256:288171134a2ff3bfb1a2f54f119e77cd1b81c29fc1265a2356f3e8d14c7d58c4"}, +] +windows-curses = [ + {file = "windows_curses-2.3.0-cp310-cp310-win32.whl", hash = "sha256:a3a63a0597729e10f923724c2cf972a23ea677b400d2387dee1d668cf7116177"}, + {file = "windows_curses-2.3.0-cp310-cp310-win_amd64.whl", hash = "sha256:7a35eda4cb120b9e1a5ae795f3bc06c55b92c9d391baba6be1903285a05f3551"}, + {file = "windows_curses-2.3.0-cp36-cp36m-win32.whl", hash = "sha256:4d5fb991d1b90a41c2332f02241a1f84c8a1e6bc8f6e0d26f532d0da7a9f7b51"}, + {file = "windows_curses-2.3.0-cp36-cp36m-win_amd64.whl", hash = "sha256:170c0d941c2e0cdf864e7f0441c1bdf0709232bf4aa7ce7f54d90fc76a4c0504"}, + {file = "windows_curses-2.3.0-cp37-cp37m-win32.whl", hash = "sha256:d5cde8ec6d582aa77af791eca54f60858339fb3f391945f9cad11b1ab71062e3"}, + {file = "windows_curses-2.3.0-cp37-cp37m-win_amd64.whl", hash = "sha256:e913dc121446d92b33fe4f5bcca26d3a34e4ad19f2af160370d57c3d1e93b4e1"}, + {file = "windows_curses-2.3.0-cp38-cp38-win32.whl", hash = "sha256:fbc2131cec57e422c6660e6cdb3420aff5be5169b8e45bb7c471f884b0590a2b"}, + {file = "windows_curses-2.3.0-cp38-cp38-win_amd64.whl", hash = "sha256:cc5fa913780d60f4a40824d374a4f8ca45b4e205546e83a2d85147315a57457e"}, + {file = "windows_curses-2.3.0-cp39-cp39-win32.whl", hash = "sha256:935be95cfdb9213f6f5d3d5bcd489960e3a8fbc9b574e7b2e8a3a3cc46efff49"}, + {file = "windows_curses-2.3.0-cp39-cp39-win_amd64.whl", hash = "sha256:c860f596d28377e47f322b7382be4d3573fd76d1292234996bb7f72e0bc0ed0d"}, +] +zipp = [ + {file = "zipp-3.6.0-py3-none-any.whl", hash = "sha256:9fe5ea21568a0a70e50f273397638d39b03353731e6cbbb3fd8502a33fec40bc"}, + {file = "zipp-3.6.0.tar.gz", hash = "sha256:71c644c5369f4a6e07636f0aa966270449561fcea2e3d6747b8d23efaa9d7832"}, +] diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pick-1.4.0/pyproject.toml new/pick-2.1.0/pyproject.toml --- old/pick-1.4.0/pyproject.toml 2022-07-24 07:38:13.000000000 +0200 +++ new/pick-2.1.0/pyproject.toml 2022-11-06 07:58:43.000000000 +0100 @@ -1,10 +1,10 @@ [tool.poetry] name = "pick" -version = "1.4.0" +version = "2.1.0" description = "Pick an option in the terminal with a simple GUI" authors = ["wong2 <wonderf...@gmail.com>"] license = "MIT" -readme = "README.rst" +readme = "README.md" repository = "https://github.com/wong2/pick" homepage = "https://github.com/wong2/pick" keywords = ["terminal", "gui"] @@ -14,8 +14,8 @@ windows-curses = {version = "^2.2.0", platform = "win32"} [tool.poetry.dev-dependencies] -pytest = "^6.2.5" -mypy = "^0.961" +pytest = "^7.1.3" +mypy = "^0.971" pre-commit = "^2.20.0" [build-system] diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pick-1.4.0/src/pick/__init__.py new/pick-2.1.0/src/pick/__init__.py --- old/pick-1.4.0/src/pick/__init__.py 2022-07-24 07:38:13.000000000 +0200 +++ new/pick-2.1.0/src/pick/__init__.py 2022-11-06 07:58:43.000000000 +0100 @@ -1,8 +1,14 @@ import curses from dataclasses import dataclass, field -from typing import Generic, Callable, List, Optional, Dict, Union, Tuple, TypeVar +from typing import Any, List, Optional, Sequence, Tuple, TypeVar, Union, Generic -__all__ = ["Picker", "pick"] +__all__ = ["Picker", "pick", "Option"] + + +@dataclass +class Option: + label: str + value: Any KEYS_ENTER = (curses.KEY_ENTER, ord("\n"), ord("\r")) @@ -10,37 +16,23 @@ KEYS_DOWN = (curses.KEY_DOWN, ord("j")) KEYS_SELECT = (curses.KEY_RIGHT, ord(" ")) -CUSTOM_HANDLER_RETURN_T = TypeVar("CUSTOM_HANDLER_RETURN_T") -KEY_T = int -OPTIONS_MAP_VALUE_T = TypeVar("OPTIONS_MAP_VALUE_T") -PICK_RETURN_T = Tuple[OPTIONS_MAP_VALUE_T, int] +SYMBOL_CIRCLE_FILLED = "(x)" +SYMBOL_CIRCLE_EMPTY = "( )" +OPTION_T = TypeVar("OPTION_T", str, Option) +PICK_RETURN_T = Tuple[OPTION_T, int] -@dataclass -class Picker(Generic[CUSTOM_HANDLER_RETURN_T, OPTIONS_MAP_VALUE_T]): - """The :class:`Picker <Picker>` object - :param options: a list of options to choose from - :param title: (optional) a title above options list - :param multiselect: (optional) if true its possible to select multiple values by hitting SPACE, defaults to False - :param indicator: (optional) custom the selection indicator - :param default_index: (optional) set this if the default selected option is not the first one - :param options_map_func: (optional) a mapping function to pass each option through before displaying - """ - - options: List[OPTIONS_MAP_VALUE_T] +@dataclass +class Picker(Generic[OPTION_T]): + options: Sequence[OPTION_T] title: Optional[str] = None indicator: str = "*" default_index: int = 0 multiselect: bool = False min_selection_count: int = 0 - options_map_func: Callable[[OPTIONS_MAP_VALUE_T], Optional[str]] = str - all_selected: List[int] = field(init=False, default_factory=list) - custom_handlers: Dict[KEY_T, Callable[["Picker"], CUSTOM_HANDLER_RETURN_T]] = field( - init=False, default_factory=dict - ) + selected_indexes: List[int] = field(init=False, default_factory=list) index: int = field(init=False, default=0) - scroll_top: int = field(init=False, default=0) def __post_init__(self) -> None: if len(self.options) == 0: @@ -54,16 +46,8 @@ "min_selection_count is bigger than the available options, you will not be able to make any selection" ) - if not callable(self.options_map_func): - raise ValueError("options_map_func must be a callable function") - self.index = self.default_index - def register_custom_handler( - self, key: KEY_T, func: Callable[["Picker"], CUSTOM_HANDLER_RETURN_T] - ) -> None: - self.custom_handlers[key] = func - def move_up(self) -> None: self.index -= 1 if self.index < 0: @@ -76,10 +60,10 @@ def mark_index(self) -> None: if self.multiselect: - if self.index in self.all_selected: - self.all_selected.remove(self.index) + if self.index in self.selected_indexes: + self.selected_indexes.remove(self.index) else: - self.all_selected.append(self.index) + self.selected_indexes.append(self.index) def get_selected(self) -> Union[List[PICK_RETURN_T], PICK_RETURN_T]: """return the current selected option as a tuple: (option, index) @@ -87,7 +71,7 @@ """ if self.multiselect: return_tuples = [] - for selected in self.all_selected: + for selected in self.selected_indexes: return_tuples.append((self.options[selected], selected)) return return_tuples else: @@ -98,30 +82,31 @@ return self.title.split("\n") + [""] return [] - def get_option_lines(self) -> Union[List[str], List[Tuple[str, int]]]: - lines: Union[List[str], List[Tuple[str, int]]] = [] # type: ignore[assignment] + def get_option_lines(self) -> List[str]: + lines: List[str] = [] for index, option in enumerate(self.options): - option_as_str = self.options_map_func(option) - if index == self.index: prefix = self.indicator else: prefix = len(self.indicator) * " " - line: Union[Tuple[str, int], str] - if self.multiselect and index in self.all_selected: - format = curses.color_pair(1) - line = ("{0} {1}".format(prefix, option_as_str), format) - else: - line = "{0} {1}".format(prefix, option_as_str) - lines.append(line) # type: ignore[arg-type] + if self.multiselect: + symbol = ( + SYMBOL_CIRCLE_FILLED + if index in self.selected_indexes + else SYMBOL_CIRCLE_EMPTY + ) + prefix = f"{prefix} {symbol}" + + option_as_str = option.label if isinstance(option, Option) else option + lines.append(f"{prefix} {option_as_str}") return lines def get_lines(self) -> Tuple[List, int]: title_lines = self.get_title_lines() option_lines = self.get_option_lines() - lines = title_lines + option_lines # type: ignore[operator] + lines = title_lines + option_lines current_line = self.index + len(title_lines) + 1 return lines, current_line @@ -136,25 +121,19 @@ lines, current_line = self.get_lines() # calculate how many lines we should scroll, relative to the top - if current_line <= self.scroll_top: - self.scroll_top = 0 - elif current_line - self.scroll_top > max_rows: - self.scroll_top = current_line - max_rows + scroll_top = 0 + if current_line > max_rows: + scroll_top = current_line - max_rows - lines_to_draw = lines[self.scroll_top : self.scroll_top + max_rows] + lines_to_draw = lines[scroll_top : scroll_top + max_rows] for line in lines_to_draw: - if type(line) is tuple: - screen.addnstr(y, x, line[0], max_x - 2, line[1]) - else: - screen.addnstr(y, x, line, max_x - 2) + screen.addnstr(y, x, line, max_x - 2) y += 1 screen.refresh() - def run_loop( - self, screen - ) -> Union[List[PICK_RETURN_T], PICK_RETURN_T, CUSTOM_HANDLER_RETURN_T]: + def run_loop(self, screen) -> Union[List[PICK_RETURN_T], PICK_RETURN_T]: while True: self.draw(screen) c = screen.getch() @@ -165,16 +144,12 @@ elif c in KEYS_ENTER: if ( self.multiselect - and len(self.all_selected) < self.min_selection_count + and len(self.selected_indexes) < self.min_selection_count ): continue return self.get_selected() elif c in KEYS_SELECT and self.multiselect: self.mark_index() - elif c in self.custom_handlers: - ret = self.custom_handlers[c](self) - if ret: - return ret def config_curses(self) -> None: try: @@ -182,50 +157,32 @@ curses.use_default_colors() # hide the cursor curses.curs_set(0) - # add some color for multi_select - # @todo make colors configurable - curses.init_pair(1, curses.COLOR_GREEN, curses.COLOR_WHITE) except: # Curses failed to initialize color support, eg. when TERM=vt100 curses.initscr() - def _start( - self, screen - ) -> Union[List[PICK_RETURN_T], PICK_RETURN_T, CUSTOM_HANDLER_RETURN_T]: + def _start(self, screen): self.config_curses() return self.run_loop(screen) - def start( - self, - ) -> Union[List[PICK_RETURN_T], PICK_RETURN_T, CUSTOM_HANDLER_RETURN_T]: + def start(self): return curses.wrapper(self._start) def pick( - options: List[OPTIONS_MAP_VALUE_T], + options: Sequence[OPTION_T], title: Optional[str] = None, indicator: str = "*", default_index: int = 0, multiselect: bool = False, min_selection_count: int = 0, - options_map_func: Callable[[OPTIONS_MAP_VALUE_T], Optional[str]] = str, -) -> Union[List[PICK_RETURN_T], PICK_RETURN_T]: - """Construct and start a :class:`Picker <Picker>`. - - Usage:: - - >>> from pick import pick - >>> title = 'Please choose an option: ' - >>> options = ['option1', 'option2', 'option3'] - >>> option, index = pick(options, title) - """ - picker = Picker( +): + picker: Picker = Picker( options, title, indicator, default_index, multiselect, min_selection_count, - options_map_func, ) return picker.start() diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pick-1.4.0/tests/test_pick.py new/pick-2.1.0/tests/test_pick.py --- old/pick-1.4.0/tests/test_pick.py 2022-07-24 07:38:13.000000000 +0200 +++ new/pick-2.1.0/tests/test_pick.py 2022-11-06 07:58:43.000000000 +0100 @@ -1,12 +1,10 @@ -from typing import Dict, Optional - -from pick import Picker +from pick import Picker, Option def test_move_up_down(): title = "Please choose an option: " options = ["option1", "option2", "option3"] - picker: Picker[str, str] = Picker(options, title) + picker = Picker(options, title) picker.move_up() assert picker.get_selected() == ("option3", 2) picker.move_down() @@ -17,14 +15,14 @@ def test_default_index(): title = "Please choose an option: " options = ["option1", "option2", "option3"] - picker: Picker[str, str] = Picker(options, title, default_index=1) + picker = Picker(options, title, default_index=1) assert picker.get_selected() == ("option2", 1) def test_get_lines(): title = "Please choose an option: " options = ["option1", "option2", "option3"] - picker: Picker[str, str] = Picker(options, title, indicator="*") + picker = Picker(options, title, indicator="*") lines, current_line = picker.get_lines() assert lines == [title, "", "* option1", " option2", " option3"] assert current_line == 3 @@ -32,7 +30,7 @@ def test_no_title(): options = ["option1", "option2", "option3"] - picker: Picker[str, str] = Picker(options) + picker = Picker(options) lines, current_line = picker.get_lines() assert current_line == 1 @@ -40,9 +38,7 @@ def test_multi_select(): title = "Please choose an option: " options = ["option1", "option2", "option3"] - picker: Picker[str, str] = Picker( - options, title, multiselect=True, min_selection_count=1 - ) + picker = Picker(options, title, multiselect=True, min_selection_count=1) assert picker.get_selected() == [] picker.mark_index() assert picker.get_selected() == [("option1", 0)] @@ -51,16 +47,11 @@ assert picker.get_selected() == [("option1", 0), ("option2", 1)] -def test_options_map_func(): - title = "Please choose an option: " - options = [{"label": "option1"}, {"label": "option2"}, {"label": "option3"}] - - def get_label(option: Dict[str, str]) -> Optional[str]: - return option.get("label") - - picker: Picker[str, Dict[str, str]] = Picker( - options, title, indicator="*", options_map_func=get_label - ) - lines, current_line = picker.get_lines() - assert lines == [title, "", "* option1", " option2", " option3"] - assert picker.get_selected() == ({"label": "option1"}, 0) +def test_option(): + options = [Option("option1", 101), Option("option2", 102), Option("option3", 103)] + picker = Picker(options) + picker.move_down() + option, index = picker.get_selected() + assert index == 1 + assert isinstance(option, Option) + assert option.value == 102