diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile
index 1ac5fa1..fdb27d0 100644
--- a/.devcontainer/Dockerfile
+++ b/.devcontainer/Dockerfile
@@ -1,4 +1,4 @@
-FROM python:3.8
+FROM python:3.12
RUN apt update && apt install -y vim
diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index 69fdf6a..5a2a420 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -13,7 +13,7 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
- python-version: ['3.8', '3.9', '3.10']
+ python-version: ['3.8', '3.9', '3.10', '3.11', '3.12', '3.13']
steps:
- uses: actions/checkout@v3
with:
@@ -27,24 +27,17 @@ jobs:
python -m pip install --upgrade pip
pip install poetry
poetry install
- echo "CODEQL_PYTHON=$(which python)" >> $GITHUB_ENV
- name: Linting
run: |
- poetry run flake8
+ poetry run ruff check .
- name: Testing
run: |
poetry run pytest
- - name: Publish coverage
- uses: codecov/codecov-action@v1
- with:
- file: ./coverage.xml
- fail_ci_if_error: true
- verbose: true
win:
runs-on: ubuntu-latest
strategy:
matrix:
- python-version: ['3.8', '3.9', '3.10']
+ python-version: ['3.8', '3.9', '3.10', '3.11', '3.12', '3.13']
steps:
- uses: actions/checkout@v3
with:
@@ -61,13 +54,42 @@ jobs:
echo "CODEQL_PYTHON=$(which python)" >> $GITHUB_ENV
- name: Linting
run: |
- poetry run flake8
+ poetry run ruff check .
- name: Testing
run: |
poetry run pytest
- - name: Publish coverage
- uses: codecov/codecov-action@v1
+
+ quality:
+ runs-on: ubuntu-latest
+ needs: [win, linux]
+ steps:
+ - uses: actions/checkout@v3
+ with:
+ fetch-depth: 0
+ - name: Set up Python ${{ matrix.python-version }}
+ uses: actions/setup-python@v4
+ with:
+ python-version: ${{ matrix.python-version }}
+ - name: Install dependencies
+ run: |
+ python -m pip install --upgrade pip
+ pip install poetry
+ poetry install
+ - name: Linting
+ run: |
+ poetry run ruff check .
+ - name: Testing
+ run: |
+ poetry run pytest
+ - name: SonarQube Scan
+ uses: sonarsource/sonarqube-scan-action@v4
+ env:
+ SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
+
+ - name: SonarQube Quality Gate check
+ id: sonarqube-quality-gate-check
+ uses: sonarsource/sonarqube-quality-gate-action@master
with:
- file: ./coverage.xml
- fail_ci_if_error: true
- verbose: true
+ pollingTimeoutSec: 600
+ env:
+ SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
\ No newline at end of file
diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml
index 7893bec..f12c09b 100644
--- a/.github/workflows/publish.yml
+++ b/.github/workflows/publish.yml
@@ -12,7 +12,7 @@ jobs:
- name: Set up Python
uses: actions/setup-python@v4
with:
- python-version: '3.10'
+ python-version: '3.12'
- name: Install dependencies
run: |
python -m pip install --upgrade pip
@@ -20,7 +20,7 @@ jobs:
poetry install
- name: Linting
run: |
- poetry run flake8
+ poetry run ruff check .
- name: Testing
run: |
poetry run pytest
diff --git a/.gitignore b/.gitignore
index e233c53..def8a10 100644
--- a/.gitignore
+++ b/.gitignore
@@ -106,3 +106,4 @@ venv.bak/
local
.vscode/
+.ruff_cache
\ No newline at end of file
diff --git a/README.md b/README.md
index 27d2ca2..a34b156 100644
--- a/README.md
+++ b/README.md
@@ -1,7 +1,6 @@
# interrogatio
- [](https://pypi.org/project/interrogatio/)  [](https://github.com/ffaraone/interrogatio/actions) [](https://codecov.io/gh/ffaraone/interrogatio)
-
+ [](https://pypi.org/project/interrogatio/)  [](https://github.com/ffaraone/interrogatio/actions) [](https://sonarcloud.io/summary/new_code?id=ffaraone_interrogatio) [](https://sonarcloud.io/summary/new_code?id=ffaraone_interrogatio)
A python library to prompt users for inputs in a terminal application.
diff --git a/docs/conf.py b/docs/conf.py
index 1050a85..20d77f4 100644
--- a/docs/conf.py
+++ b/docs/conf.py
@@ -1,4 +1,3 @@
-# -*- coding: utf-8 -*-
#
# Configuration file for the Sphinx documentation builder.
#
@@ -16,20 +15,20 @@
import sys
from datetime import datetime
-sys.path.insert(0, os.path.abspath('..'))
+sys.path.insert(0, os.path.abspath(".."))
# on_rtd = os.environ.get('READTHEDOCS', None) == 'True'
# -- Project information -----------------------------------------------------
-project = 'interrogatio'
-copyright = '{}, Francesco Faraone.'.format(datetime.now().year)
-author = 'Francesco Faraone'
+project = "interrogatio"
+copyright = f"{datetime.now().year}, Francesco Faraone."
+author = "Francesco Faraone"
# The short X.Y version
-version = ''
+version = ""
# The full version, including alpha/beta/rc tags
-release = '1.0.0'
+release = "1.0.0"
# -- General configuration ---------------------------------------------------
@@ -42,7 +41,7 @@
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
# ones.
extensions = [
- 'sphinx.ext.autodoc',
+ "sphinx.ext.autodoc",
]
# if not on_rtd: # only import and set the theme if we're building docs locally
@@ -52,16 +51,16 @@
# Add any paths that contain templates here, relative to this directory.
-templates_path = ['_templates']
+templates_path = ["_templates"]
# The suffix(es) of source filenames.
# You can specify multiple suffix as a list of string:
#
# source_suffix = ['.rst', '.md']
-source_suffix = '.rst'
+source_suffix = ".rst"
# The master toctree document.
-master_doc = 'index'
+master_doc = "index"
# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.
@@ -73,7 +72,7 @@
# List of patterns, relative to source directory, that match files and
# directories to ignore when looking for source files.
# This pattern also affects html_static_path and html_extra_path.
-exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store']
+exclude_patterns = ["_build", "Thumbs.db", ".DS_Store"]
# The name of the Pygments (syntax highlighting) style to use.
pygments_style = None
@@ -85,7 +84,7 @@
# a list of builtin themes.
#
-html_theme = 'sphinx_rtd_theme'
+html_theme = "sphinx_rtd_theme"
# Theme options are theme-specific and customize the look and feel of a theme
# further. For a list of options available for each theme, see the
@@ -96,7 +95,7 @@
# Add any paths that contain custom static files (such as style sheets) here,
# relative to this directory. They are copied after the builtin static files,
# so a file named "default.css" will overwrite the builtin "default.css".
-html_static_path = ['_static']
+html_static_path = ["_static"]
# Custom sidebar templates, must be a dictionary that maps document names
# to template names.
@@ -112,7 +111,7 @@
# -- Options for HTMLHelp output ---------------------------------------------
# Output file base name for HTML help builder.
-htmlhelp_basename = 'interrogatiodoc'
+htmlhelp_basename = "interrogatiodoc"
# -- Options for LaTeX output ------------------------------------------------
@@ -121,15 +120,12 @@
# The paper size ('letterpaper' or 'a4paper').
#
# 'papersize': 'letterpaper',
-
# The font size ('10pt', '11pt' or '12pt').
#
# 'pointsize': '10pt',
-
# Additional stuff for the LaTeX preamble.
#
# 'preamble': '',
-
# Latex figure (float) alignment
#
# 'figure_align': 'htbp',
@@ -139,8 +135,13 @@
# (source start file, target name, title,
# author, documentclass [howto, manual, or own class]).
latex_documents = [
- (master_doc, 'interrogatio.tex', 'interrogatio Documentation',
- 'Francesco Faraone', 'manual'),
+ (
+ master_doc,
+ "interrogatio.tex",
+ "interrogatio Documentation",
+ "Francesco Faraone",
+ "manual",
+ ),
]
@@ -148,10 +149,7 @@
# One entry per manual page. List of tuples
# (source start file, name, description, authors, manual section).
-man_pages = [
- (master_doc, 'interrogatio', 'interrogatio Documentation',
- [author], 1)
-]
+man_pages = [(master_doc, "interrogatio", "interrogatio Documentation", [author], 1)]
# -- Options for Texinfo output ----------------------------------------------
@@ -160,9 +158,15 @@
# (source start file, target name, title, author,
# dir menu entry, description, category)
texinfo_documents = [
- (master_doc, 'interrogatio', 'interrogatio Documentation',
- author, 'interrogatio', 'One line description of project.',
- 'Miscellaneous'),
+ (
+ master_doc,
+ "interrogatio",
+ "interrogatio Documentation",
+ author,
+ "interrogatio",
+ "One line description of project.",
+ "Miscellaneous",
+ ),
]
@@ -181,7 +185,7 @@
# epub_uid = ''
# A list of files that should not be packed into the epub file.
-epub_exclude_files = ['search.html']
+epub_exclude_files = ["search.html"]
# -- Extension configuration -------------------------------------------------
diff --git a/interrogatio/__init__.py b/interrogatio/__init__.py
index 415a03b..6fba4ee 100644
--- a/interrogatio/__init__.py
+++ b/interrogatio/__init__.py
@@ -1,15 +1,12 @@
-from pkg_resources import DistributionNotFound, get_distribution
+from importlib_metadata import version
from interrogatio.core.dialog import dialogus
from interrogatio.core.prompt import interrogatio
-__all__ = ('dialogus', 'interrogatio')
+__all__ = ("dialogus", "interrogatio")
-try:
- __version__ = get_distribution('interrogatio').version
-except DistributionNotFound: # pragma: no cover
- __version__ = '0.0.0'
+__version__ = version("interrogatio")
def get_version():
diff --git a/interrogatio/core/dialog.py b/interrogatio/core/dialog.py
index 3f47229..ee04b38 100644
--- a/interrogatio/core/dialog.py
+++ b/interrogatio/core/dialog.py
@@ -6,8 +6,7 @@
from interrogatio.themes import for_dialog, set_theme
from interrogatio.widgets.wizard import WizardDialog
-
-__all__ = ['dialogus']
+__all__ = ["dialogus"]
def show_dialog(
@@ -16,19 +15,24 @@ def show_dialog(
intro=None,
summary=False,
fast_forward=False,
- next_text='Next',
- previous_text='Previous',
- cancel_text='Cancel',
- finish_text='Finish',
+ next_text="Next",
+ previous_text="Previous",
+ cancel_text="Cancel",
+ finish_text="Finish",
):
handlers = [get_instance(q) for q in questions]
app = Application(
layout=Layout(
WizardDialog(
- title, handlers,
- intro=intro, summary=summary, fast_forward=fast_forward,
- next_text=next_text, previous_text=previous_text,
- cancel_text=cancel_text, finish_text=finish_text,
+ title,
+ handlers,
+ intro=intro,
+ summary=summary,
+ fast_forward=fast_forward,
+ next_text=next_text,
+ previous_text=previous_text,
+ cancel_text=cancel_text,
+ finish_text=finish_text,
),
),
mouse_support=False,
@@ -51,11 +55,11 @@ def dialogus(
intro=None,
summary=False,
fast_forward=False,
- next_text='Next',
- previous_text='Previous',
- cancel_text='Cancel',
- finish_text='Finish',
- theme='default',
+ next_text="Next",
+ previous_text="Previous",
+ cancel_text="Cancel",
+ finish_text="Finish",
+ theme="default",
):
"""
Show a dialog with inputs as defined in the questions parameter and returns
diff --git a/interrogatio/core/exceptions.py b/interrogatio/core/exceptions.py
index 857a5e7..7914506 100644
--- a/interrogatio/core/exceptions.py
+++ b/interrogatio/core/exceptions.py
@@ -14,8 +14,9 @@ class ValidationError(Exception):
"""
Exception raised when validation fails.
"""
+
def __init__(self, message):
- super(ValidationError, self).__init__()
+ super().__init__()
self._message = message
def __str__(self):
diff --git a/interrogatio/core/prompt.py b/interrogatio/core/prompt.py
index 6b3e03d..914ab65 100644
--- a/interrogatio/core/prompt.py
+++ b/interrogatio/core/prompt.py
@@ -9,11 +9,10 @@
from interrogatio.handlers import get_instance
from interrogatio.themes import for_prompt, set_theme
+__all__ = ["interrogatio"]
-__all__ = ['interrogatio']
-
-def interrogatio(questions, theme='default'):
+def interrogatio(questions, theme="default"):
"""
Prompts user for inputs as defined in the questions parameter and returns
a dictionary with the answers.
@@ -83,7 +82,7 @@ def interrogatio(questions, theme='default'):
break
else:
print_formatted_text(
- FormattedText([('class:error', handler.errors[0])]),
+ FormattedText([("class:error", handler.errors[0])]),
style=for_prompt(),
)
return answers
diff --git a/interrogatio/core/utils.py b/interrogatio/core/utils.py
index de815dd..ed6e04d 100644
--- a/interrogatio/core/utils.py
+++ b/interrogatio/core/utils.py
@@ -3,67 +3,65 @@
def _validate_validator_object(obj):
- if 'name' not in obj:
- raise InvalidQuestionError(
- 'You must specify a name for the validator.')
+ if "name" not in obj:
+ raise InvalidQuestionError("You must specify a name for the validator.")
- if obj['name'] not in validators.get_registered():
+ if obj["name"] not in validators.get_registered():
raise InvalidQuestionError(
f'Validator {obj["name"]} does not exists.',
)
- if 'args' in obj and not isinstance(obj['args'], dict):
- raise InvalidQuestionError('Validator arguments must be a dictionary.')
+ if "args" in obj and not isinstance(obj["args"], dict):
+ raise InvalidQuestionError("Validator arguments must be a dictionary.")
def _validate_question(q): # noqa: CCR001
+ if "name" not in q:
+ raise InvalidQuestionError("You must specify a name for the question.")
- if 'name' not in q:
- raise InvalidQuestionError('You must specify a name for the question.')
-
- if 'type' not in q:
- raise InvalidQuestionError('You must specify a question type.')
+ if "type" not in q:
+ raise InvalidQuestionError("You must specify a question type.")
- q_type = q['type']
+ q_type = q["type"]
if q_type not in handlers.get_registered():
raise InvalidQuestionError(
- f'Unsupported question type: {q_type}.',
+ f"Unsupported question type: {q_type}.",
)
- if q_type in ('selectone', 'selectmany'):
- if 'values' not in q:
+ if q_type in ("selectone", "selectmany"):
+ if "values" not in q:
raise InvalidQuestionError(
- 'You must specify at least one choice for type choice.',
+ "You must specify at least one choice for type choice.",
)
- values = q['values']
+ values = q["values"]
if values:
if not isinstance(values, (list, tuple)):
if not callable(values):
raise InvalidQuestionError(
- 'Choices must be a list, tuple of tuples or callable.',
+ "Choices must be a list, tuple of tuples or callable.",
)
else:
first_value = values[0]
if not isinstance(first_value, (list, tuple)):
raise InvalidQuestionError(
- 'Choices must be a list or tuple of tuples.',
+ "Choices must be a list or tuple of tuples.",
)
if len(first_value) != 2:
raise InvalidQuestionError(
- 'Every choice must be a tuple (value, label).',
+ "Every choice must be a tuple (value, label).",
)
- if 'validators' in q:
- if not isinstance(q['validators'], (list, tuple)):
- raise InvalidQuestionError('Validators must be a list or tuple.')
+ if "validators" in q:
+ if not isinstance(q["validators"], (list, tuple)):
+ raise InvalidQuestionError("Validators must be a list or tuple.")
validator_instances = []
- for v in q['validators']:
+ for v in q["validators"]:
if not isinstance(v, (validators.Validator, dict)):
raise InvalidQuestionError(
- 'Validators must be a list of '
- 'interrogatio.validators.Validator'
- ' instances or a list of validator objects.',
+ "Validators must be a list of "
+ "interrogatio.validators.Validator"
+ " instances or a list of validator objects.",
)
if isinstance(v, dict):
@@ -72,12 +70,12 @@ def _validate_question(q): # noqa: CCR001
validator_instances.append(v)
else:
validator_instances.append(v)
- q['validators'] = validator_instances
+ q["validators"] = validator_instances
- if 'disabled' in q:
- if not (isinstance(q['disabled'], bool) or callable(q['disabled'])):
+ if "disabled" in q:
+ if not (isinstance(q["disabled"], bool) or callable(q["disabled"])):
raise InvalidQuestionError(
- 'Disabled flag must be a boolean or callable.',
+ "Disabled flag must be a boolean or callable.",
)
diff --git a/interrogatio/handlers/__init__.py b/interrogatio/handlers/__init__.py
index cc64ba8..86ab33b 100644
--- a/interrogatio/handlers/__init__.py
+++ b/interrogatio/handlers/__init__.py
@@ -1,5 +1,7 @@
from interrogatio.handlers.base import QHandler # noqa
from interrogatio.handlers.registry import ( # noqa
- register, get_instance, get_registered,
+ register,
+ get_instance,
+ get_registered,
)
from interrogatio.handlers.builtins import * # noqa
diff --git a/interrogatio/handlers/base.py b/interrogatio/handlers/base.py
index c82aa71..155f419 100644
--- a/interrogatio/handlers/base.py
+++ b/interrogatio/handlers/base.py
@@ -7,7 +7,7 @@
from interrogatio.core.exceptions import ValidationError
__all__ = [
- 'QHandler',
+ "QHandler",
]
@@ -45,7 +45,7 @@ def get_layout(self):
:rtype: :class:`~prompt_toolkit.layout.Layout`
"""
raise NotImplementedError(
- 'Subclass must implements `get_layout` method.',
+ "Subclass must implements `get_layout` method.",
)
def get_question(self):
@@ -62,7 +62,7 @@ def get_value(self):
:rtype: str
"""
raise NotImplementedError(
- 'Subclass must implements `get_value` method.',
+ "Subclass must implements `get_value` method.",
)
def get_formatted_value(self):
@@ -79,7 +79,7 @@ def get_widget_init_kwargs(self):
:rtype: dict
"""
raise NotImplementedError(
- 'Subclass must implements `get_widget_init_kwargs` method.',
+ "Subclass must implements `get_widget_init_kwargs` method.",
)
def get_init_extra_args(self):
@@ -91,7 +91,7 @@ def get_init_extra_args(self):
:return: a dictionary containing the initialization extra arguments.
:rtype: dict
"""
- return self.get_question().get('extra_args', dict())
+ return self.get_question().get("extra_args", {})
@abstractmethod
def get_widget_class(self):
@@ -102,7 +102,7 @@ def get_widget_class(self):
:rtype: class
"""
raise NotImplementedError(
- 'Subclass must implements `get_widget_class` method.',
+ "Subclass must implements `get_widget_class` method.",
)
def get_widget(self):
@@ -141,20 +141,21 @@ def get_answer(self):
Returns dictionary with the question variable as key and the answer
as the value.
"""
- return {self.get_question()['name']: self.to_python()}
+ return {self.get_question()["name"]: self.to_python()}
def get_variable_name(self):
"""
Returns the name of the variable of this question.
"""
- return self._question['name']
+ return self._question["name"]
def get_label(self):
"""
Returns the label of the variable of this question.
"""
return self._question.get(
- 'label', self.get_variable_name().capitalize(),
+ "label",
+ self.get_variable_name().capitalize(),
)
def is_disabled(self, context=None):
@@ -162,7 +163,7 @@ def is_disabled(self, context=None):
If disabled flag specified, it is evaluated if needed and returned.
By default, all questions are enabled.
"""
- disabled = self._question.get('disabled', False)
+ disabled = self._question.get("disabled", False)
if callable(disabled):
return disabled(context)
else:
@@ -175,7 +176,7 @@ def is_valid(self, context=None):
If the answer isn't valid, it also set the errors property to a list
of error messages.
"""
- validators = self._question.get('validators', [])
+ validators = self._question.get("validators", [])
self._errors = []
for validator in validators:
try:
diff --git a/interrogatio/handlers/builtins.py b/interrogatio/handlers/builtins.py
index 6173e89..e4b3573 100644
--- a/interrogatio/handlers/builtins.py
+++ b/interrogatio/handlers/builtins.py
@@ -18,25 +18,24 @@
from interrogatio.widgets import DateRange, MaskedInput, SelectMany, SelectOne
-@register('input')
+@register("input")
class StringHandler(QHandler):
-
def get_widget_class(self):
return TextArea
def get_widget_init_kwargs(self):
- kwgars = dict(
- multiline=self._question.get('multiline', False),
- style='class:input.answer',
- )
- default = self.get_question().get('default')
+ kwgars = {
+ "multiline": self._question.get("multiline", False),
+ "style": "class:input.answer",
+ }
+ default = self.get_question().get("default")
if default and not callable(default):
- kwgars['text'] = default
+ kwgars["text"] = default
return kwgars
def set_context(self, context):
widget = self.get_widget()
- default = self.get_question().get('default')
+ default = self.get_question().get("default")
if default and callable(default):
widget.text = default(context)
widget.buffer.cursor_position = len(widget.text)
@@ -45,25 +44,29 @@ def get_layout(self):
widget = self.get_widget()
vsplit_components = [widget]
widget.buffer.cursor_position = len(widget.text)
- if 'message' in self._question and self._question['message']:
+ if "message" in self._question and self._question["message"]:
vsplit_components.insert(
0,
Label(
- self._question['message'],
+ self._question["message"],
dont_extend_width=True,
- style='class:input.question',
+ style="class:input.question",
),
)
hsplit_components = [VSplit(vsplit_components, padding=1)]
- if 'description' in self._question and self._question['description']:
+ if "description" in self._question and self._question["description"]:
hsplit_components.insert(
0,
Window(
FormattedTextControl(
- FormattedText([(
- 'class:input.question',
- self._question['description'],
- )]),
+ FormattedText(
+ [
+ (
+ "class:input.question",
+ self._question["description"],
+ )
+ ]
+ ),
),
wrap_lines=True,
height=D(min=1, max=5, preferred=3),
@@ -75,26 +78,25 @@ def get_value(self):
return self.get_widget().text
-@register('password')
+@register("password")
class PasswordHandler(QHandler):
-
def get_widget_class(self):
return TextArea
def get_widget_init_kwargs(self):
- kwgars = dict(
- multiline=self._question.get('multiline', False),
- password=True,
- style='class:password.answer',
- )
- default = self.get_question().get('default')
+ kwgars = {
+ "multiline": self._question.get("multiline", False),
+ "password": True,
+ "style": "class:password.answer",
+ }
+ default = self.get_question().get("default")
if default and not callable(default):
- kwgars['text'] = default
+ kwgars["text"] = default
return kwgars
def set_context(self, context):
widget = self.get_widget()
- default = self.get_question().get('default')
+ default = self.get_question().get("default")
if default and callable(default):
widget.text = default(context)
widget.buffer.cursor_position = len(widget.text)
@@ -106,25 +108,29 @@ def get_layout(self):
widget = self.get_widget()
widget.buffer.cursor_position = len(widget.text)
vsplit_components = [widget]
- if 'message' in self._question and self._question['message']:
+ if "message" in self._question and self._question["message"]:
vsplit_components.insert(
0,
Label(
- self._question['message'],
+ self._question["message"],
dont_extend_width=True,
- style='class:password.question',
+ style="class:password.question",
),
)
hsplit_components = [VSplit(vsplit_components, padding=1)]
- if 'description' in self._question and self._question['description']:
+ if "description" in self._question and self._question["description"]:
hsplit_components.insert(
0,
Window(
FormattedTextControl(
- FormattedText([(
- 'class:password.question',
- self._question['description'],
- )]),
+ FormattedText(
+ [
+ (
+ "class:password.question",
+ self._question["description"],
+ )
+ ]
+ ),
),
wrap_lines=True,
height=D(min=1, max=5, preferred=3),
@@ -133,9 +139,8 @@ def get_layout(self):
return HSplit(hsplit_components, padding=1)
-@register('selectone')
+@register("selectone")
class SelectOneHandler(QHandler):
-
def get_widget_class(self):
return SelectOne
@@ -143,50 +148,54 @@ def get_value(self):
return self.get_widget().current_value
def get_widget_init_kwargs(self):
- values = self.get_question()['values']
- kwargs = dict(
- values=values if not callable(values) else None,
- style='class:selectone.answer',
- )
- default = self.get_question().get('default')
+ values = self.get_question()["values"]
+ kwargs = {
+ "values": values if not callable(values) else None,
+ "style": "class:selectone.answer",
+ }
+ default = self.get_question().get("default")
if default and not callable(default):
- kwargs['default'] = default
+ kwargs["default"] = default
return kwargs
def set_context(self, context):
widget = self.get_widget()
- values = self.get_question()['values']
+ values = self.get_question()["values"]
if callable(values):
values = values(context)
widget.values = values or []
widget.current_value = values[0][0] if values else None
- default = self.get_question().get('default')
+ default = self.get_question().get("default")
if default and callable(default):
widget.value = default(context)
def get_layout(self):
vsplit_components = [self.get_widget()]
- if 'message' in self._question and self._question['message']:
+ if "message" in self._question and self._question["message"]:
vsplit_components.insert(
0,
Label(
- self._question['message'],
+ self._question["message"],
dont_extend_width=True,
dont_extend_height=False,
- style='class:selectone.question',
+ style="class:selectone.question",
),
)
hsplit_components = [VSplit(vsplit_components, padding=1)]
- if 'description' in self._question and self._question['description']:
+ if "description" in self._question and self._question["description"]:
hsplit_components.insert(
0,
Window(
FormattedTextControl(
- FormattedText([(
- 'class:selectone.question',
- self._question['description'],
- )]),
+ FormattedText(
+ [
+ (
+ "class:selectone.question",
+ self._question["description"],
+ )
+ ]
+ ),
),
wrap_lines=True,
height=D(min=1, max=5, preferred=3),
@@ -196,19 +205,19 @@ def get_layout(self):
def get_formatted_value(self):
format = self._question.get(
- 'formatting_template',
- '${label} (${value})',
+ "formatting_template",
+ "${label} (${value})",
)
value = self.get_value()
- options = {t[0]: t[1] for t in self._question['values']}
+ options = {t[0]: t[1] for t in self._question["values"]}
return string.Template(format).safe_substitute(
- label=options[value], value=value,
+ label=options[value],
+ value=value,
)
-@register('selectmany')
+@register("selectmany")
class SelectManyHandler(QHandler):
-
def get_widget_class(self):
return SelectMany
@@ -216,43 +225,43 @@ def get_value(self):
return self.get_widget().value
def get_widget_init_kwargs(self):
- values = self.get_question()['values']
- kwargs = dict(
- values=values if not callable(values) else None,
- style='class:selectmany.answer',
- )
- default = self.get_question().get('default')
+ values = self.get_question()["values"]
+ kwargs = {
+ "values": values if not callable(values) else None,
+ "style": "class:selectmany.answer",
+ }
+ default = self.get_question().get("default")
if default and not callable(default):
- kwargs['default'] = default
+ kwargs["default"] = default
return kwargs
def set_context(self, context):
widget = self.get_widget()
- values = self.get_question()['values']
+ values = self.get_question()["values"]
if callable(values):
values = values(context)
widget.values = values or []
- default = self.get_question().get('default')
+ default = self.get_question().get("default")
if default and callable(default):
widget.value = default(context)
def get_layout(self):
widget = self.get_widget()
vsplit_components = [widget]
- if 'message' in self._question and self._question['message']:
+ if "message" in self._question and self._question["message"]:
vsplit_components.insert(
0,
Label(
- self._question['message'],
+ self._question["message"],
dont_extend_width=True,
dont_extend_height=False,
- style='class:selectone.question',
+ style="class:selectone.question",
),
)
- btn_all = Button('All', widget.select_all)
- btn_none = Button('None', widget.select_none)
+ btn_all = Button("All", widget.select_all)
+ btn_none = Button("None", widget.select_none)
buttons = Box(
body=VSplit([btn_all, btn_none], padding=1),
height=D(min=1, max=3, preferred=3),
@@ -260,15 +269,19 @@ def get_layout(self):
)
hsplit_components = [buttons, VSplit(vsplit_components, padding=1)]
- if 'description' in self._question and self._question['description']:
+ if "description" in self._question and self._question["description"]:
hsplit_components.insert(
0,
Window(
FormattedTextControl(
- FormattedText([(
- 'class:selectone.question',
- self._question['description'],
- )]),
+ FormattedText(
+ [
+ (
+ "class:selectone.question",
+ self._question["description"],
+ )
+ ]
+ ),
),
wrap_lines=True,
height=D(min=1, max=5, preferred=3),
@@ -277,7 +290,6 @@ def get_layout(self):
return HSplit(hsplit_components, padding=1)
def get_keybindings(self):
-
bindings = super().get_keybindings()
@bindings.add(Keys.Tab)
@@ -292,79 +304,83 @@ def _s_tab(event):
def get_formatted_value(self):
format = self._question.get(
- 'formatting_template',
- '${label} (${value})',
+ "formatting_template",
+ "${label} (${value})",
)
values = self.get_value()
if not values:
- return ''
+ return ""
- if callable(self._question['values']):
+ if callable(self._question["values"]):
options = {t[0]: t[1] for t in self.get_widget().values}
else:
- options = {t[0]: t[1] for t in self._question['values']}
+ options = {t[0]: t[1] for t in self._question["values"]}
formatted_values = []
for idx, value in enumerate(values):
if idx > 14:
- formatted_values.append('...')
+ formatted_values.append("...")
break
formatted_values.append(
string.Template(format).safe_substitute(
- label=options[value], value=value,
+ label=options[value],
+ value=value,
),
)
- return ', '.join(formatted_values)
+ return ", ".join(formatted_values)
-@register('maskedinput')
+@register("maskedinput")
class MaskedInputHandler(QHandler):
-
def get_widget_class(self):
return MaskedInput
def get_widget_init_kwargs(self):
- mask = self.get_question()['mask']
- kwargs = dict(
- style='class:input.answer',
- mask=mask,
- )
- default = self.get_question().get('default')
+ mask = self.get_question()["mask"]
+ kwargs = {
+ "style": "class:input.answer",
+ "mask": mask,
+ }
+ default = self.get_question().get("default")
if default and not callable(default):
- kwargs['default'] = default
+ kwargs["default"] = default
return kwargs
def set_context(self, context):
widget = self.get_widget()
- default = self.get_question().get('default')
+ default = self.get_question().get("default")
if default and callable(default):
widget.value = default(context)
def get_layout(self):
widget = self.get_widget()
vsplit_components = [widget]
- if 'message' in self._question and self._question['message']:
+ if "message" in self._question and self._question["message"]:
vsplit_components.insert(
0,
Label(
- self._question['message'],
+ self._question["message"],
dont_extend_width=True,
- style='class:input.question',
+ style="class:input.question",
),
)
hsplit_components = [VSplit(vsplit_components, padding=1)]
- if 'description' in self._question and self._question['description']:
+ if "description" in self._question and self._question["description"]:
hsplit_components.insert(
0,
Window(
FormattedTextControl(
- FormattedText([(
- 'class:input.question',
- self._question['description'],
- )]),
+ FormattedText(
+ [
+ (
+ "class:input.question",
+ self._question["description"],
+ )
+ ]
+ ),
),
wrap_lines=True,
height=D(min=1, max=5, preferred=3),
@@ -376,58 +392,61 @@ def get_value(self):
return self.get_widget().value
-@register('date')
+@register("date")
class DateHandler(QHandler):
-
def get_widget_class(self):
return MaskedInput
def get_widget_init_kwargs(self):
- kwargs = dict(
- style='class:input.answer',
- mask='____-__-__',
- allowed_chars=string.digits,
- )
- default = self.get_question().get('default')
+ kwargs = {
+ "style": "class:input.answer",
+ "mask": "____-__-__",
+ "allowed_chars": string.digits,
+ }
+ default = self.get_question().get("default")
if default and not callable(default):
if isinstance(default, (date, datetime)):
- kwargs['default'] = default.strftime('%Y-%m-%d')
+ kwargs["default"] = default.strftime("%Y-%m-%d")
else:
- kwargs['default'] = default
+ kwargs["default"] = default
return kwargs
def set_context(self, context):
widget = self.get_widget()
- default = self.get_question().get('default')
+ default = self.get_question().get("default")
if default and callable(default):
value = default(context)
if isinstance(value, (date, datetime)):
- widget.value = value.strftime('%Y-%m-%d')
+ widget.value = value.strftime("%Y-%m-%d")
else:
widget.value = value
def get_layout(self):
widget = self.get_widget()
vsplit_components = [widget]
- if 'message' in self._question and self._question['message']:
+ if "message" in self._question and self._question["message"]:
vsplit_components.insert(
0,
Label(
- self._question['message'],
+ self._question["message"],
dont_extend_width=True,
- style='class:input.question',
+ style="class:input.question",
),
)
hsplit_components = [VSplit(vsplit_components, padding=1)]
- if 'description' in self._question and self._question['description']:
+ if "description" in self._question and self._question["description"]:
hsplit_components.insert(
0,
Window(
FormattedTextControl(
- FormattedText([(
- 'class:input.question',
- self._question['description'],
- )]),
+ FormattedText(
+ [
+ (
+ "class:input.question",
+ self._question["description"],
+ )
+ ]
+ ),
),
wrap_lines=True,
height=D(min=1, max=5, preferred=3),
@@ -441,12 +460,12 @@ def to_python(self):
return
question = self.get_question()
- if 'timezone' in question:
- tzinfo = pytz.timezone(question['timezone'])
+ if "timezone" in question:
+ tzinfo = pytz.timezone(question["timezone"])
else:
tzinfo = pytz.timezone(get_localzone_name())
- year, month, day = value.split('-')
+ year, month, day = value.split("-")
return tzinfo.localize(
datetime(int(year), int(month), int(day)),
)
@@ -455,84 +474,87 @@ def get_value(self):
return self.get_widget().value
-@register('daterange')
+@register("daterange")
class DateRangeHandler(QHandler):
-
def get_widget_class(self):
return DateRange
def get_widget_init_kwargs(self): # noqa: CCR001
- kwargs = dict(
- style='class:input.answer',
- )
- if 'from_label' in self._question:
- kwargs['from_label'] = self._question['from_label']
- if 'to_label' in self._question:
- kwargs['to_label'] = self._question['to_label']
- default = self.get_question().get('default')
+ kwargs = {
+ "style": "class:input.answer",
+ }
+ if "from_label" in self._question:
+ kwargs["from_label"] = self._question["from_label"]
+ if "to_label" in self._question:
+ kwargs["to_label"] = self._question["to_label"]
+ default = self.get_question().get("default")
if default and not callable(default):
- kwargs['default'] = {}
- default_from = default.get('from')
+ kwargs["default"] = {}
+ default_from = default.get("from")
if default_from:
if isinstance(default_from, (date, datetime)):
- kwargs['default']['from'] = default_from.strftime(
- '%Y-%m-%d',
+ kwargs["default"]["from"] = default_from.strftime(
+ "%Y-%m-%d",
)
else:
- kwargs['default']['from'] = default_from
- default_to = default.get('to')
+ kwargs["default"]["from"] = default_from
+ default_to = default.get("to")
if default_to:
if isinstance(default_to, (date, datetime)):
- kwargs['default']['to'] = default_to.strftime('%Y-%m-%d')
+ kwargs["default"]["to"] = default_to.strftime("%Y-%m-%d")
else:
- kwargs['default']['to'] = default_to
+ kwargs["default"]["to"] = default_to
return kwargs
def set_context(self, context):
widget = self.get_widget()
- default = self.get_question().get('default')
+ default = self.get_question().get("default")
if default and callable(default):
value = default(context)
default_value = {}
- default_from = value.get('from')
+ default_from = value.get("from")
if default_from:
if isinstance(default_from, (date, datetime)):
- default_value['from'] = default_from.strftime(
- '%Y-%m-%d',
+ default_value["from"] = default_from.strftime(
+ "%Y-%m-%d",
)
else:
- default_value['from'] = default_from
- default_to = value.get('to')
+ default_value["from"] = default_from
+ default_to = value.get("to")
if default_to:
if isinstance(default_to, (date, datetime)):
- default_value['to'] = default_to.strftime('%Y-%m-%d')
+ default_value["to"] = default_to.strftime("%Y-%m-%d")
else:
- default_value['to'] = default_to
+ default_value["to"] = default_to
widget.value = default_value
def get_layout(self):
widget = self.get_widget()
vsplit_components = [widget]
- if 'message' in self._question and self._question['message']:
+ if "message" in self._question and self._question["message"]:
vsplit_components.insert(
0,
Label(
- self._question['message'],
+ self._question["message"],
dont_extend_width=True,
dont_extend_height=False,
- style='class:input.question',
+ style="class:input.question",
),
)
hsplit_components = [VSplit(vsplit_components, padding=1)]
- if 'description' in self._question and self._question['description']:
+ if "description" in self._question and self._question["description"]:
hsplit_components.insert(
0,
Window(
FormattedTextControl(
- FormattedText([(
- 'class:input.question',
- self._question['description'],
- )]),
+ FormattedText(
+ [
+ (
+ "class:input.question",
+ self._question["description"],
+ )
+ ]
+ ),
),
wrap_lines=True,
height=D(min=1, max=5, preferred=3),
@@ -542,8 +564,8 @@ def get_layout(self):
def to_python(self):
question = self.get_question()
- if 'timezone' in question:
- tzinfo = pytz.timezone(question['timezone'])
+ if "timezone" in question:
+ tzinfo = pytz.timezone(question["timezone"])
else:
tzinfo = pytz.timezone(get_localzone_name())
@@ -552,21 +574,21 @@ def to_python(self):
value = self.get_value()
- from_value = value.get('from')
+ from_value = value.get("from")
if from_value:
- year, month, day = from_value.split('-')
+ year, month, day = from_value.split("-")
from_date = tzinfo.localize(
datetime(int(year), int(month), int(day)),
)
- to_value = value.get('to')
+ to_value = value.get("to")
if to_value:
- year, month, day = to_value.split('-')
+ year, month, day = to_value.split("-")
to_date = tzinfo.localize(datetime(int(year), int(month), int(day)))
return {
- 'from': from_date,
- 'to': to_date,
+ "from": from_date,
+ "to": to_date,
}
def get_value(self):
@@ -574,16 +596,16 @@ def get_value(self):
def get_formatted_value(self):
format = self._question.get(
- 'formatting_template',
- 'from ${start} - to ${end}',
+ "formatting_template",
+ "from ${start} - to ${end}",
)
value = self.get_value()
return string.Template(format).safe_substitute(
- start=value['from'], end=value['to'],
+ start=value["from"],
+ end=value["to"],
)
def get_keybindings(self):
-
bindings = super().get_keybindings()
@bindings.add(Keys.Tab)
diff --git a/interrogatio/handlers/registry.py b/interrogatio/handlers/registry.py
index 3c99d75..27cc66b 100644
--- a/interrogatio/handlers/registry.py
+++ b/interrogatio/handlers/registry.py
@@ -5,14 +5,14 @@
class QHandlersRegistry(dict):
def register(self, alias, clazz):
if alias in self:
- raise AlreadyRegisteredError(f'alias `{alias}` already exists.')
+ raise AlreadyRegisteredError(f"alias `{alias}` already exists.")
self[alias] = clazz
def get_registered(self):
return list(self.keys())
def get_instance(self, question):
- qtype = question['type']
+ qtype = question["type"]
clazz = self[qtype]
return clazz(question)
@@ -52,16 +52,17 @@ def get_registered():
def register(name):
if name in get_registry().get_registered():
raise AlreadyRegisteredError(
- f'The handler `{name}` is already registered.',
+ f"The handler `{name}` is already registered.",
)
def _wrapper(cls):
if not issubclass(cls, QHandler):
raise ValueError(
- 'The provided class must be a subclass of QHandler.',
+ "The provided class must be a subclass of QHandler.",
)
get_registry().register(name, cls)
return cls
+
return _wrapper
diff --git a/interrogatio/main.py b/interrogatio/main.py
index 025bd07..1460df9 100644
--- a/interrogatio/main.py
+++ b/interrogatio/main.py
@@ -5,10 +5,11 @@
try:
import yaml
- FORMAT_CHOICES = ['json', 'yaml']
+
+ FORMAT_CHOICES = ["json", "yaml"]
except ImportError:
yaml = None
- FORMAT_CHOICES = ['json']
+ FORMAT_CHOICES = ["json"]
from interrogatio import dialogus, interrogatio
@@ -26,78 +27,76 @@ def _write_answers(args, answers):
def _add_common_arguments(parser):
parser.add_argument(
- '--input',
- '-i',
- type=argparse.FileType('r'),
+ "--input",
+ "-i",
+ type=argparse.FileType("r"),
required=True,
- help='Input file with questions',
+ help="Input file with questions",
)
parser.add_argument(
- '--output',
- '-o',
- type=argparse.FileType('w'),
+ "--output",
+ "-o",
+ type=argparse.FileType("w"),
default=sys.stdout,
- help='Output file to write answers to (Default: STDOUT)',
+ help="Output file to write answers to (Default: STDOUT)",
)
if len(FORMAT_CHOICES) > 1:
parser.add_argument(
- '--input-format',
+ "--input-format",
choices=FORMAT_CHOICES,
- default='json',
- help='Questions file format (Default: json)',
+ default="json",
+ help="Questions file format (Default: json)",
)
parser.add_argument(
- '--output-format',
+ "--output-format",
choices=FORMAT_CHOICES,
- default='json',
- help='Answers file format (Default: json)',
+ default="json",
+ help="Answers file format (Default: json)",
)
parser.add_argument(
- '--theme',
- '-t',
- default='default',
- help='Name of the UI theme to use (Default: default)',
+ "--theme",
+ "-t",
+ default="default",
+ help="Name of the UI theme to use (Default: default)",
)
def main_dialogus():
parser = argparse.ArgumentParser(
- description='Show a wizard dialog to prompt user for questions.',
+ description="Show a wizard dialog to prompt user for questions.",
)
_add_common_arguments(parser)
parser.add_argument(
- '--title',
- help='Title of the dialog',
+ "--title",
+ help="Title of the dialog",
)
parser.add_argument(
- '--intro',
- help='Specify the text of the introduction step (Default: no intro)',
+ "--intro",
+ help="Specify the text of the introduction step (Default: no intro)",
)
parser.add_argument(
- '--summary',
- action='store_true',
+ "--summary",
+ action="store_true",
help=(
- 'Show a summary with answers as the '
- 'latest step (Default: no summary)'
+ "Show a summary with answers as the " "latest step (Default: no summary)"
),
)
- for button in ('previous', 'next', 'cancel', 'finish'):
+ for button in ("previous", "next", "cancel", "finish"):
cap_btn = button.capitalize()
parser.add_argument(
- f'--{button}',
+ f"--{button}",
default=cap_btn,
help=(
- f'Customize the text of the "{button}" '
- f'button (Default: {cap_btn})'
+ f'Customize the text of the "{button}" ' f"button (Default: {cap_btn})"
),
)
args = parser.parse_args()
- if args.input_format == 'yaml':
+ if args.input_format == "yaml":
args.deserialize = partial(yaml.load, Loader=yaml.FullLoader)
args.serialize = yaml.dump
else:
@@ -105,13 +104,13 @@ def main_dialogus():
args.serialize = json.dump
kwargs = {
- 'intro': args.intro,
- 'summary': args.summary,
- 'title': args.title,
- 'previous_text': args.previous,
- 'next_text': args.next,
- 'cancel_text': args.cancel,
- 'finish_text': args.finish,
+ "intro": args.intro,
+ "summary": args.summary,
+ "title": args.title,
+ "previous_text": args.previous,
+ "next_text": args.next,
+ "cancel_text": args.cancel,
+ "finish_text": args.finish,
}
_write_answers(args, dialogus(_load_questions(args), **kwargs))
@@ -119,13 +118,13 @@ def main_dialogus():
def main_interrogatio():
parser = argparse.ArgumentParser(
- description='Prompt user for questions.',
+ description="Prompt user for questions.",
)
_add_common_arguments(parser)
args = parser.parse_args()
- if args.input_format == 'yaml':
+ if args.input_format == "yaml":
args.deserialize = partial(yaml.load, Loader=yaml.FullLoader)
args.serialize = yaml.dump
else:
diff --git a/interrogatio/shortcuts/__init__.py b/interrogatio/shortcuts/__init__.py
index d22021e..5807d29 100644
--- a/interrogatio/shortcuts/__init__.py
+++ b/interrogatio/shortcuts/__init__.py
@@ -1 +1 @@
-from interrogatio.shortcuts.dialogs import * # noqa
\ No newline at end of file
+from interrogatio.shortcuts.dialogs import * # noqa
diff --git a/interrogatio/shortcuts/dialogs.py b/interrogatio/shortcuts/dialogs.py
index c05e0d2..0ffa378 100644
--- a/interrogatio/shortcuts/dialogs.py
+++ b/interrogatio/shortcuts/dialogs.py
@@ -8,20 +8,20 @@
from interrogatio.themes import for_dialog
__all__ = [
- 'yes_no_dialog',
- 'button_dialog',
- 'input_dialog',
- 'message_dialog',
- 'radiolist_dialog',
- 'progress_dialog',
+ "yes_no_dialog",
+ "button_dialog",
+ "input_dialog",
+ "message_dialog",
+ "radiolist_dialog",
+ "progress_dialog",
]
def yes_no_dialog(
- title='',
- text='',
- yes_text='Yes',
- no_text='No',
+ title="",
+ text="",
+ yes_text="Yes",
+ no_text="No",
style=None,
):
style = style or for_dialog()
@@ -35,8 +35,8 @@ def yes_no_dialog(
def button_dialog(
- title='',
- text='',
+ title="",
+ text="",
buttons=None,
style=None,
):
@@ -50,45 +50,70 @@ def button_dialog(
def input_dialog(
- title='', text='', ok_text='OK', cancel_text='Cancel',
- completer=None, password=False, style=None,
+ title="",
+ text="",
+ ok_text="OK",
+ cancel_text="Cancel",
+ completer=None,
+ password=False,
+ style=None,
):
style = style or for_dialog()
return pt_input_dialog(
- title=title, text=text, ok_text=ok_text,
- cancel_text=cancel_text, completer=completer,
- password=password, style=style,
+ title=title,
+ text=text,
+ ok_text=ok_text,
+ cancel_text=cancel_text,
+ completer=completer,
+ password=password,
+ style=style,
)
def message_dialog(
- title='', text='', ok_text='Ok', style=None,
+ title="",
+ text="",
+ ok_text="Ok",
+ style=None,
):
style = style or for_dialog()
return pt_message_dialog(
- title=title, text=text,
- ok_text=ok_text, style=style,
+ title=title,
+ text=text,
+ ok_text=ok_text,
+ style=style,
)
def radiolist_dialog(
- title='', text='', ok_text='Ok', cancel_text='Cancel',
- values=None, style=None,
+ title="",
+ text="",
+ ok_text="Ok",
+ cancel_text="Cancel",
+ values=None,
+ style=None,
):
style = style or for_dialog()
return pt_radiolist_dialog(
- title=title, text=text,
- ok_text=ok_text, cancel_text=cancel_text,
- values=values, style=style,
+ title=title,
+ text=text,
+ ok_text=ok_text,
+ cancel_text=cancel_text,
+ values=values,
+ style=style,
)
def progress_dialog(
- title='', text='',
- run_callback=None, style=None,
+ title="",
+ text="",
+ run_callback=None,
+ style=None,
):
style = style or for_dialog()
return pt_progress_dialog(
- title=title, text=text,
- run_callback=run_callback, style=style,
+ title=title,
+ text=text,
+ run_callback=run_callback,
+ style=style,
)
diff --git a/interrogatio/themes/base.py b/interrogatio/themes/base.py
index a61dc3a..6f12f21 100644
--- a/interrogatio/themes/base.py
+++ b/interrogatio/themes/base.py
@@ -1,6 +1,6 @@
import json
-from prompt_toolkit.styles import default_ui_style, merge_styles, Style
+from prompt_toolkit.styles import Style, default_ui_style, merge_styles
from interrogatio.core.exceptions import (
AlreadyRegisteredError,
@@ -8,69 +8,70 @@
)
__all__ = [
- 'Theme',
- 'register',
- 'for_dialog',
- 'for_prompt',
- 'set_theme',
+ "Theme",
+ "register",
+ "for_dialog",
+ "for_prompt",
+ "set_theme",
]
class Theme:
-
def __init__(self):
- self._prompt_styles = dict()
- self._dialog_styles = dict()
- self._name = ''
+ self._prompt_styles = {}
+ self._dialog_styles = {}
+ self._name = ""
def load(self, filename):
- with open(filename, 'r') as f:
+ with open(filename) as f:
tmp = json.load(f)
- self._name = tmp['name']
- self._prompt_styles = tmp['prompt']
- self._dialog_styles = tmp['dialog']
+ self._name = tmp["name"]
+ self._prompt_styles = tmp["prompt"]
+ self._dialog_styles = tmp["dialog"]
def for_prompt(self):
- return merge_styles([
- default_ui_style(),
- Style(list(self._prompt_styles.items())),
- ])
+ return merge_styles(
+ [
+ default_ui_style(),
+ Style(list(self._prompt_styles.items())),
+ ]
+ )
def for_dialog(self):
- return merge_styles([
- default_ui_style(),
- Style(list(self._dialog_styles.items())),
- ])
+ return merge_styles(
+ [
+ default_ui_style(),
+ Style(list(self._dialog_styles.items())),
+ ]
+ )
def save(self, filename):
- with open(filename, 'w') as f:
+ with open(filename, "w") as f:
json.dump(
{
- 'name': self._name,
- 'prompt': self._prompt_styles,
- 'dialog': self._dialog_styles,
+ "name": self._name,
+ "prompt": self._prompt_styles,
+ "dialog": self._dialog_styles,
},
f,
indent=2,
)
-class ThemeRegistry(object):
-
+class ThemeRegistry:
def __init__(self):
self._themes = {}
- self._current_theme = 'default'
+ self._current_theme = "default"
def register(self, alias, theme):
assert isinstance(theme, Theme)
if alias in self._themes:
- raise AlreadyRegisteredError(
- 'theme {} already registered'.format(alias))
+ raise AlreadyRegisteredError(f"theme {alias} already registered")
self._themes[alias] = theme
def set_current(self, alias):
if alias not in self._themes:
- raise ThemeNotFoundError('theme {} not registered'.format(alias))
+ raise ThemeNotFoundError(f"theme {alias} not registered")
self._current_theme = alias
def get_current(self):
diff --git a/interrogatio/themes/builtins.py b/interrogatio/themes/builtins.py
index 290f6c3..3cbcba1 100644
--- a/interrogatio/themes/builtins.py
+++ b/interrogatio/themes/builtins.py
@@ -1,29 +1,33 @@
import os
-from interrogatio.themes.base import register, Theme
+from interrogatio.themes.base import Theme, register
class DefaultTheme(Theme):
def __init__(self):
- super(DefaultTheme, self).__init__()
- self.load(os.path.join(
- os.path.dirname(__file__),
- 'theme_files',
- 'default.json',
- ))
+ super().__init__()
+ self.load(
+ os.path.join(
+ os.path.dirname(__file__),
+ "theme_files",
+ "default.json",
+ )
+ )
-register('default', DefaultTheme())
+register("default", DefaultTheme())
class PurpleTheme(Theme):
def __init__(self):
- super(PurpleTheme, self).__init__()
- self.load(os.path.join(
- os.path.dirname(__file__),
- 'theme_files',
- 'purple.json',
- ))
+ super().__init__()
+ self.load(
+ os.path.join(
+ os.path.dirname(__file__),
+ "theme_files",
+ "purple.json",
+ )
+ )
-register('purple', PurpleTheme())
+register("purple", PurpleTheme())
diff --git a/interrogatio/validators/base.py b/interrogatio/validators/base.py
index 2820282..fd23f88 100644
--- a/interrogatio/validators/base.py
+++ b/interrogatio/validators/base.py
@@ -1,8 +1,7 @@
from abc import ABCMeta, abstractmethod
-
__all__ = [
- 'Validator',
+ "Validator",
]
@@ -10,7 +9,8 @@ class Validator(metaclass=ABCMeta):
"""
Abstract class for validators.
"""
- def __init__(self, message='invalid input'):
+
+ def __init__(self, message="invalid input"):
self.message = message
@abstractmethod
diff --git a/interrogatio/validators/builtins.py b/interrogatio/validators/builtins.py
index c051380..86334a0 100644
--- a/interrogatio/validators/builtins.py
+++ b/interrogatio/validators/builtins.py
@@ -7,26 +7,25 @@
from interrogatio.validators.base import Validator
from interrogatio.validators.registry import register
-
__all__ = [
- 'RequiredValidator',
- 'RegexValidator',
- 'URLValidator',
- 'EmailValidator',
- 'MinLengthValidator',
- 'MaxLengthValidator',
- 'NumberValidator',
- 'IntegerValidator',
- 'IPv4Validator',
- 'RangeValidator',
- 'MinValidator',
- 'MaxValidator',
- 'DateTimeValidator',
- 'DateTimeRangeValidator',
+ "RequiredValidator",
+ "RegexValidator",
+ "URLValidator",
+ "EmailValidator",
+ "MinLengthValidator",
+ "MaxLengthValidator",
+ "NumberValidator",
+ "IntegerValidator",
+ "IPv4Validator",
+ "RangeValidator",
+ "MinValidator",
+ "MaxValidator",
+ "DateTimeValidator",
+ "DateTimeRangeValidator",
]
-@register('required')
+@register("required")
class RequiredValidator(Validator):
def __init__(self, message=None):
"""
@@ -35,8 +34,8 @@ def __init__(self, message=None):
:param message: the error message in case that validation fails.
:type message: str
"""
- super(RequiredValidator, self).__init__(
- message=message or 'this field is required',
+ super().__init__(
+ message=message or "this field is required",
)
def validate(self, value, context=None):
@@ -44,7 +43,7 @@ def validate(self, value, context=None):
raise ValidationError(self.message)
-@register('regex')
+@register("regex")
class RegexValidator(Validator):
def __init__(self, expr, message=None, inverse_match=None):
"""
@@ -57,32 +56,29 @@ def __init__(self, expr, message=None, inverse_match=None):
:param inverse_match: invert the match of the expression.
:type inverse_match: bool
"""
- super(RegexValidator, self).__init__(
- message=message or f'this field does not match {expr}',
+ super().__init__(
+ message=message or f"this field does not match {expr}",
)
self.regex = re.compile(expr)
self.inverse_match = inverse_match
def validate(self, value, context=None):
regex_matches = self.regex.search(str(value))
- invalid_input = (
- regex_matches if self.inverse_match else not regex_matches
- )
+ invalid_input = regex_matches if self.inverse_match else not regex_matches
if invalid_input:
raise ValidationError(self.message)
-@register('email')
+@register("email")
class EmailValidator(Validator):
-
def __init__(self, message=None):
"""
Initialise the ``email`` validator.
:param message: the error message in case that validation fails.
:type message: str
"""
- super(EmailValidator, self).__init__(
- message=message or 'this field must be an email address',
+ super().__init__(
+ message=message or "this field must be an email address",
)
def validate(self, value, context=None):
@@ -90,18 +86,17 @@ def validate(self, value, context=None):
raise ValidationError(self.message)
-@register('url')
+@register("url")
class URLValidator(Validator):
-
def __init__(self, message=None):
- super().__init__(message=message or 'this field must be an url')
+ super().__init__(message=message or "this field must be an url")
def validate(self, value, context=None):
if value and validators.url(value) is not True:
raise ValidationError(self.message)
-@register('min-length')
+@register("min-length")
class MinLengthValidator(Validator):
def __init__(self, min_length, message=None):
"""
@@ -116,22 +111,19 @@ def __init__(self, min_length, message=None):
self.min_length = min_length
self.message = message or (
- 'the length of this field must be at '
- 'least {} characters long'.format(self.min_length)
+ "the length of this field must be at "
+ f"least {self.min_length} characters long"
)
def validate(self, value, context=None):
try:
- if (
- value
- and validators.length(value, min=self.min_length) is not True
- ):
+ if value and validators.length(value, min=self.min_length) is not True:
raise ValidationError(message=self.message)
except (TypeError, AssertionError):
raise ValidationError(message=self.message)
-@register('max-length')
+@register("max-length")
class MaxLengthValidator(Validator):
def __init__(self, max_length, message=None):
"""
@@ -145,25 +137,21 @@ def __init__(self, max_length, message=None):
"""
self.max_length = max_length
self.message = message or (
- 'the length of this field must be at '
- f'most {max_length} characters long'
+ "the length of this field must be at " f"most {max_length} characters long"
)
def validate(self, value, context=None):
try:
- if (
- value
- and validators.length(value, max=self.max_length) is not True
- ):
+ if value and validators.length(value, max=self.max_length) is not True:
raise ValidationError(message=self.message)
except (TypeError, AssertionError):
raise ValidationError(message=self.message)
-@register('number')
+@register("number")
class NumberValidator(Validator):
def __init__(self, message=None):
- self.message = message or 'this field must be a number'
+ self.message = message or "this field must be a number"
def validate(self, value, context=None):
try:
@@ -172,10 +160,10 @@ def validate(self, value, context=None):
raise ValidationError(message=self.message)
-@register('integer')
+@register("integer")
class IntegerValidator(Validator):
def __init__(self, message=None):
- self.message = message or 'this field must be an integer'
+ self.message = message or "this field must be an integer"
def validate(self, value, context=None):
try:
@@ -187,92 +175,94 @@ def validate(self, value, context=None):
raise ValidationError(message=self.message)
-@register('ipv4')
+@register("ipv4")
class IPv4Validator(Validator):
def __init__(self, message=None):
- self.message = message or 'this field must be an IPv4 address'
+ self.message = message or "this field must be an IPv4 address"
def validate(self, value, context=None):
if value and validators.ipv4(value) is not True:
raise ValidationError(message=self.message)
-@register('range')
+@register("range")
class RangeValidator(Validator):
def __init__(self, min=None, max=None, message=None):
self.min = min
self.max = max
self.message = message or (
- f'this field must be a number between {min} and {max}'
+ f"this field must be a number between {min} and {max}"
)
def validate(self, value, context=None):
try:
if (
- value is not None and value != ''
+ value is not None
+ and value != ""
and validators.between(
value,
min=self.min,
max=self.max,
- ) is not True
+ )
+ is not True
):
raise ValidationError(message=self.message)
except (TypeError, AssertionError):
raise ValidationError(message=self.message)
-@register('min')
+@register("min")
class MinValidator(Validator):
def __init__(self, min=None, message=None):
self.min = min
- self.message = (
- message or f'this field must be greater or equal to {min}'
- )
+ self.message = message or f"this field must be greater or equal to {min}"
def validate(self, value, context=None):
try:
if (
- value is not None and value != ''
+ value is not None
+ and value != ""
and validators.between(
value,
min=self.min,
- ) is not True
+ )
+ is not True
):
raise ValidationError(message=self.message)
except (TypeError, AssertionError):
raise ValidationError(message=self.message)
-@register('max')
+@register("max")
class MaxValidator(Validator):
def __init__(self, max=None, message=None):
self.max = max
- self.message = (
- message or f'this field must be smaller or equal to {max}'
- )
+ self.message = message or f"this field must be smaller or equal to {max}"
def validate(self, value, context=None):
try:
if (
- value is not None and value != ''
+ value is not None
+ and value != ""
and validators.between(
value,
max=self.max,
- ) is not True
+ )
+ is not True
):
raise ValidationError(message=self.message)
except (TypeError, AssertionError):
raise ValidationError(message=self.message)
-@register('datetime')
+@register("datetime")
class DateTimeValidator(Validator):
- def __init__(self, format_pattern='%Y-%m-%dT%H:%M:%S', message=None):
+ def __init__(self, format_pattern="%Y-%m-%dT%H:%M:%S", message=None):
self.format_pattern = format_pattern
- self.message = message or 'this field is not a valid datetime'
+ self.message = message or "this field is not a valid datetime"
def validate(self, value, context=None):
- if value is None or value == '':
+ if value is None or value == "":
return
try:
datetime.strptime(value, self.format_pattern)
@@ -280,22 +270,22 @@ def validate(self, value, context=None):
raise ValidationError(message=self.message)
-@register('datetimerange')
+@register("datetimerange")
class DateTimeRangeValidator(Validator):
- def __init__(self, format_pattern='%Y-%m-%d', message=None):
+ def __init__(self, format_pattern="%Y-%m-%d", message=None):
self.format_pattern = format_pattern
- self.message = message or 'this field is not a valid datetime range'
+ self.message = message or "this field is not a valid datetime range"
def validate(self, value, context=None):
- if value is None or value == '':
+ if value is None or value == "":
return
d_from = None
d_to = None
try:
- if value['from']:
- d_from = datetime.strptime(value['from'], self.format_pattern)
- if value['to']:
- d_to = datetime.strptime(value['to'], self.format_pattern)
+ if value["from"]:
+ d_from = datetime.strptime(value["from"], self.format_pattern)
+ if value["to"]:
+ d_to = datetime.strptime(value["to"], self.format_pattern)
except (TypeError, ValueError):
raise ValidationError(message=self.message)
diff --git a/interrogatio/validators/registry.py b/interrogatio/validators/registry.py
index 2f8f2b3..149d85b 100644
--- a/interrogatio/validators/registry.py
+++ b/interrogatio/validators/registry.py
@@ -5,17 +5,16 @@
class ValidatorsRegistry(dict):
def register(self, alias, clazz):
if alias in self:
- raise AlreadyRegisteredError(
- 'validator `{}` already exists.'.format(alias))
+ raise AlreadyRegisteredError(f"validator `{alias}` already exists.")
self[alias] = clazz
def get_registered(self):
return list(self.keys())
def get_instance(self, v):
- clazz = self[v['name']]
- if 'args' in v:
- return clazz(**v['args'])
+ clazz = self[v["name"]]
+ if "args" in v:
+ return clazz(**v["args"])
return clazz()
@@ -29,18 +28,19 @@ def get_registry():
def register(name):
if name in get_registry().get_registered():
raise AlreadyRegisteredError(
- f'The validator `{name}` is already registered.',
+ f"The validator `{name}` is already registered.",
)
def _wrapper(cls):
if not issubclass(cls, Validator):
raise ValueError(
- 'The provided class must be a subclass of Validator.',
+ "The provided class must be a subclass of Validator.",
)
get_registry().register(name, cls)
return cls
+
return _wrapper
diff --git a/interrogatio/widgets/base.py b/interrogatio/widgets/base.py
index 67e7136..5ed8474 100644
--- a/interrogatio/widgets/base.py
+++ b/interrogatio/widgets/base.py
@@ -14,16 +14,16 @@
from prompt_toolkit.widgets import Label, TextArea
-class SelectOne(object):
+class SelectOne:
def __init__( # noqa: CCR001
- self, values=None, default=None,
- accept_handler=None, style='',
+ self,
+ values=None,
+ default=None,
+ accept_handler=None,
+ style="",
):
-
self.values = values or []
- self.current_value = (
- values[0][0] if values and not callable(values) else None
- )
+ self.current_value = values[0][0] if values and not callable(values) else None
self._selected_index = 0
self.accept_handler = accept_handler
if default:
@@ -31,20 +31,19 @@ def __init__( # noqa: CCR001
# Key bindings.
kb = KeyBindings()
- @kb.add('up')
+ @kb.add("up")
def _(event):
if not self.values:
return
self._selected_index = max(0, self._selected_index - 1)
- @kb.add('down')
+ @kb.add("down")
def _(event):
if not self.values:
return
- self._selected_index = min(
- len(self.values) - 1, self._selected_index + 1)
+ self._selected_index = min(len(self.values) - 1, self._selected_index + 1)
- @kb.add('pageup')
+ @kb.add("pageup")
def _(event):
if not self.values:
return
@@ -54,7 +53,7 @@ def _(event):
self._selected_index - len(w.render_info.displayed_lines),
)
- @kb.add('pagedown')
+ @kb.add("pagedown")
def _(event):
if not self.values:
return
@@ -64,7 +63,7 @@ def _(event):
self._selected_index + len(w.render_info.displayed_lines),
)
- @kb.add(' ')
+ @kb.add(" ")
def _(event):
if not self.values:
return
@@ -75,22 +74,22 @@ def _(event):
if not self.values:
return
# We first check values after the selected value, then all values.
- for value in self.values[self._selected_index + 1:] + self.values:
+ for value in self.values[self._selected_index + 1 :] + self.values:
if value[1].startswith(event.data):
self._selected_index = self.values.index(value)
return
# Control and window.
self.control = FormattedTextControl(
- lambda: self._get_text_fragments(style),
- key_bindings=kb,
- focusable=True)
+ lambda: self._get_text_fragments(style), key_bindings=kb, focusable=True
+ )
self.window = Window(
content=self.control,
- style='class:radio-list',
+ style="class:radio-list",
right_margins=[ScrollbarMargin(display_arrows=True)],
- dont_extend_height=True)
+ dont_extend_height=True,
+ )
@property
def value(self):
@@ -116,29 +115,28 @@ def mouse_handler(mouse_event):
result = []
for i, value in enumerate(self.values):
- checked = (value[0] == self.current_value)
- selected = (i == self._selected_index)
+ checked = value[0] == self.current_value
+ selected = i == self._selected_index
style = out_style
if checked:
- style += ' class:radio-checked'
+ style += " class:radio-checked"
if selected:
- style += ' class:radio-selected'
+ style += " class:radio-selected"
- result.append((style, '('))
+ result.append((style, "("))
if selected:
- result.append(('[SetCursorPosition]', ''))
+ result.append(("[SetCursorPosition]", ""))
if checked:
- result.append((style, '*'))
+ result.append((style, "*"))
else:
- result.append((style, ' '))
+ result.append((style, " "))
- result.append((style, ')'))
- result.append((out_style + ' class:radio', ' '))
- result.extend(
- to_formatted_text(value[1], style=out_style + ' class:radio'))
- result.append(('', '\n'))
+ result.append((style, ")"))
+ result.append((out_style + " class:radio", " "))
+ result.extend(to_formatted_text(value[1], style=out_style + " class:radio"))
+ result.append(("", "\n"))
# Add mouse handler to all fragments.
for i, fragment in enumerate(result):
@@ -152,12 +150,14 @@ def __pt_container__(self):
return self.window
-class SelectMany(object):
+class SelectMany:
def __init__( # noqa: CCR001
- self, values=None, default=None,
- accept_handler=None, style='',
+ self,
+ values=None,
+ default=None,
+ accept_handler=None,
+ style="",
):
-
self.values = values
self.checked = None
self._selected_index = 0
@@ -168,20 +168,19 @@ def __init__( # noqa: CCR001
# Key bindings.
kb = KeyBindings()
- @kb.add('up')
+ @kb.add("up")
def _(event):
if not self.values:
return
self._selected_index = max(0, self._selected_index - 1)
- @kb.add('down')
+ @kb.add("down")
def _(event):
if not self.values:
return
- self._selected_index = min(
- len(self.values) - 1, self._selected_index + 1)
+ self._selected_index = min(len(self.values) - 1, self._selected_index + 1)
- @kb.add('pageup')
+ @kb.add("pageup")
def _(event):
if not self.values:
return
@@ -191,7 +190,7 @@ def _(event):
self._selected_index - len(w.render_info.displayed_lines),
)
- @kb.add('pagedown')
+ @kb.add("pagedown")
def _(event):
if not self.values:
return
@@ -201,7 +200,7 @@ def _(event):
self._selected_index + len(w.render_info.displayed_lines),
)
- @kb.add(' ')
+ @kb.add(" ")
def _(event):
if not self.values:
return
@@ -215,22 +214,22 @@ def _(event):
if not self.values:
return
# We first check values after the selected value, then all values.
- for value in self.values[self._selected_index + 1:] + self.values:
+ for value in self.values[self._selected_index + 1 :] + self.values:
if value[1].startswith(event.data):
self._selected_index = self.values.index(value)
return
# Control and window.
self.control = FormattedTextControl(
- lambda: self._get_text_fragments(style),
- key_bindings=kb,
- focusable=True)
+ lambda: self._get_text_fragments(style), key_bindings=kb, focusable=True
+ )
self.window = Window(
content=self.control,
- style='class:checkbox-list',
+ style="class:checkbox-list",
right_margins=[ScrollbarMargin(display_arrows=True)],
- dont_extend_height=True)
+ dont_extend_height=True,
+ )
if default:
self.value = default
@@ -253,33 +252,33 @@ def select_none(self):
def _generate_fragments(self, out_style):
result = []
for i, value in enumerate(self.values):
- checked = (value[0] in self.checked)
- selected = (i == self._selected_index)
+ checked = value[0] in self.checked
+ selected = i == self._selected_index
style = out_style
if checked:
- style += ' class:checkbox-checked'
+ style += " class:checkbox-checked"
if selected:
- style += ' class:checkbox-selected'
+ style += " class:checkbox-selected"
- result.append((style, '['))
+ result.append((style, "["))
if selected:
- result.append(('[SetCursorPosition]', ''))
+ result.append(("[SetCursorPosition]", ""))
if checked:
- result.append((style, '*'))
+ result.append((style, "*"))
else:
- result.append((style, ' '))
+ result.append((style, " "))
- result.append((style, ']'))
- result.append((out_style + ' class:checkbox', ' '))
+ result.append((style, "]"))
+ result.append((out_style + " class:checkbox", " "))
result.extend(
to_formatted_text(
value[1],
- style=out_style + ' class:checkbox',
+ style=out_style + " class:checkbox",
),
)
- result.append(('', '\n'))
+ result.append(("", "\n"))
return result
def _get_text_fragments(self, out_style): # pragma: no cover
@@ -309,15 +308,15 @@ def __pt_container__(self):
class FixedLengthBuffer(Buffer):
def __init__(self, **kwargs):
- self._max_length = kwargs.pop('max_length')
- self._allowed_chars = kwargs.pop('allowed_chars')
- self._widget = kwargs.pop('widget')
+ self._max_length = kwargs.pop("max_length")
+ self._allowed_chars = kwargs.pop("allowed_chars")
+ self._widget = kwargs.pop("widget")
super().__init__(**kwargs)
def _is_input_allowed(self, data):
if not self._allowed_chars:
return True
- return all([char in self._allowed_chars for char in data])
+ return all(char in self._allowed_chars for char in data)
def insert_text(
self,
@@ -342,10 +341,9 @@ def delete_before_cursor(self, count=1):
class FixedLengthTextArea(TextArea):
-
def __init__(
self,
- text='',
+ text="",
width=None,
height=None,
max_length=None,
@@ -353,7 +351,6 @@ def __init__(
widget=None,
style=None,
):
-
self.max_length = max_length
self.buffer = FixedLengthBuffer(
@@ -383,11 +380,10 @@ def __init__(
class MaskedInput(VSplit):
-
def __init__(
self,
mask,
- placeholder='_',
+ placeholder="_",
style=None,
default=None,
allowed_chars=None,
@@ -427,7 +423,7 @@ def __init__(
)
self._components.append(widget)
self._fields.append(widget)
- self._components.append(Label(''))
+ self._components.append(Label(""))
if default:
self.value = default
@@ -447,15 +443,18 @@ def go_next(self, component):
get_app().layout.focus_next()
def _has_value(self):
- values = ''.join([
- cmp.text for cmp in self._components
- if isinstance(cmp, FixedLengthTextArea)
- ]).strip()
+ values = "".join(
+ [
+ cmp.text
+ for cmp in self._components
+ if isinstance(cmp, FixedLengthTextArea)
+ ]
+ ).strip()
return bool(values)
def _build_value(self):
if self._has_value():
- return ''.join([cmp.text for cmp in self._components])
+ return "".join([cmp.text for cmp in self._components])
return None
@property
@@ -465,48 +464,56 @@ def value(self):
@value.setter
def value(self, val):
if len(val) != len(self._mask):
- raise ValueError('Invalid value length')
+ raise ValueError("Invalid value length")
pos = 0
- non_mask_chars = self._mask.replace(self._placeholder, '')
+ non_mask_chars = self._mask.replace(self._placeholder, "")
for char in non_mask_chars:
- val = val.replace(char, '')
+ val = val.replace(char, "")
for field in self._fields:
- field.text = val[pos:pos + field.max_length]
+ field.text = val[pos : pos + field.max_length]
pos += field.max_length
class DateRange(HSplit):
-
def __init__(
self,
- from_label='From: ',
- to_label=' to: ',
+ from_label="From: ",
+ to_label=" to: ",
style=None,
):
-
self._from = MaskedInput(
- mask='____-__-__', allowed_chars=string.digits, style=style,
+ mask="____-__-__",
+ allowed_chars=string.digits,
+ style=style,
)
self._to = MaskedInput(
- mask='____-__-__', allowed_chars=string.digits, style=style,
+ mask="____-__-__",
+ allowed_chars=string.digits,
+ style=style,
)
components = []
if from_label:
- components.append(VSplit([
- Label(from_label, dont_extend_width=True),
- self._from,
- ]))
+ components.append(
+ VSplit(
+ [
+ Label(from_label, dont_extend_width=True),
+ self._from,
+ ]
+ )
+ )
else:
components.append(self._from)
if to_label:
components.append(
- VSplit([
- Label(to_label, dont_extend_width=True),
- self._to,
- ]),
+ VSplit(
+ [
+ Label(to_label, dont_extend_width=True),
+ self._to,
+ ]
+ ),
)
else:
components.append(self._to)
@@ -516,14 +523,14 @@ def __init__(
@property
def value(self):
return {
- 'from': self._from.value,
- 'to': self._to.value,
+ "from": self._from.value,
+ "to": self._to.value,
}
@value.setter
def value(self, val):
- if 'from' in val:
- self._from.value = val['from']
+ if "from" in val:
+ self._from.value = val["from"]
- if 'to' in val:
- self._to.value = val['to']
+ if "to" in val:
+ self._to.value = val["to"]
diff --git a/interrogatio/widgets/wizard.py b/interrogatio/widgets/wizard.py
index 6c6b7eb..d2d7dbb 100644
--- a/interrogatio/widgets/wizard.py
+++ b/interrogatio/widgets/wizard.py
@@ -2,7 +2,7 @@
from prompt_toolkit.application import get_app
from prompt_toolkit.filters import has_focus
-from prompt_toolkit.formatted_text import FormattedText, HTML, to_formatted_text
+from prompt_toolkit.formatted_text import HTML, FormattedText, to_formatted_text
from prompt_toolkit.key_binding.bindings.focus import focus_next, focus_previous
from prompt_toolkit.key_binding.key_bindings import KeyBindings
from prompt_toolkit.keys import Keys
@@ -20,9 +20,15 @@
class WizardDialog:
def __init__( # noqa: CCR001
- self, title, handlers, intro=None, summary=False,
- next_text='Next', previous_text='Previous',
- cancel_text='Cancel', finish_text='Finish',
+ self,
+ title,
+ handlers,
+ intro=None,
+ summary=False,
+ next_text="Next",
+ previous_text="Previous",
+ cancel_text="Cancel",
+ finish_text="Finish",
fast_forward=False,
):
self.title = title
@@ -39,7 +45,7 @@ def __init__( # noqa: CCR001
self.label_previous = previous_text
self.label_cancel = cancel_text
self.label_finish = finish_text
- self.error_messages = ''
+ self.error_messages = ""
self.cancel_btn = Button(
text=self.label_cancel,
@@ -63,8 +69,8 @@ def __init__( # noqa: CCR001
first_selected = has_focus(self.buttons[0])
last_selected = has_focus(self.buttons[-1])
- self.buttons_kb.add('left', filter=~first_selected)(focus_previous)
- self.buttons_kb.add('right', filter=~last_selected)(focus_next)
+ self.buttons_kb.add("left", filter=~first_selected)(focus_previous)
+ self.buttons_kb.add("right", filter=~last_selected)(focus_next)
input_container = HSplit(
[
@@ -93,9 +99,9 @@ def __init__( # noqa: CCR001
)
top_container = VSplit(
[left_container, right_container],
- padding_char='│',
+ padding_char="│",
padding=1,
- padding_style='#000000',
+ padding_style="#000000",
height=D(min=10, preferred=24),
)
@@ -116,35 +122,33 @@ def __init__( # noqa: CCR001
top_container,
buttons_container,
],
- padding_char='─',
+ padding_char="─",
padding=1,
- padding_style='#000000',
+ padding_style="#000000",
),
- style='class:dialog.body',
+ style="class:dialog.body",
key_bindings=kb,
width=D(min=78, preferred=132),
),
)
self.container = Box(
- body=frame, style='class:dialog',
+ body=frame,
+ style="class:dialog",
)
def get_title(self):
- return (
- f'{self.title} - {self.current_step_idx + 1} of {len(self.steps)}'
- )
+ return f"{self.title} - {self.current_step_idx + 1} of {len(self.steps)}"
def _get_step_style(self, idx):
if idx == self.current_step_idx:
- return 'class:dialog.step.current'
+ return "class:dialog.step.current"
- if (
- self.steps[idx].get('handler')
- and self.steps[idx]['handler'].is_disabled(context=self.answers)
+ if self.steps[idx].get("handler") and self.steps[idx]["handler"].is_disabled(
+ context=self.answers
):
- return 'class:dialog.step.disabled'
+ return "class:dialog.step.disabled"
- return 'class:dialog.step'
+ return "class:dialog.step"
def get_steps_labels(self):
steps_labels = []
@@ -167,27 +171,27 @@ def get_status(self):
if self.error_messages:
return Window(
FormattedTextControl(
- FormattedText([('class:error', self.error_messages)]),
+ FormattedText([("class:error", self.error_messages)]),
),
height=1,
)
- return Label('')
+ return Label("")
def get_summary(self):
if isinstance(self.summary, bool):
- text = '\n'.join(
+ text = "\n".join(
[
- f'{handler.get_variable_name().capitalize()}:'
- f' {handler.get_formatted_value()}'
+ f"{handler.get_variable_name().capitalize()}:"
+ f" {handler.get_formatted_value()}"
for handler in self.handlers
],
)
elif callable(self.summary):
data = {
handler.get_variable_name(): {
- 'question': handler.get_question(),
- 'value': handler.get_value(),
- 'formatted_value': handler.get_formatted_value(),
+ "question": handler.get_question(),
+ "value": handler.get_value(),
+ "formatted_value": handler.get_formatted_value(),
}
for handler in self.handlers
}
@@ -205,7 +209,7 @@ def get_summary(self):
)
def get_current_step_container(self):
- return self.current_step['layout']
+ return self.current_step["layout"]
def get_buttons_container(self):
return VSplit(
@@ -222,9 +226,9 @@ def process_steps(self):
)
self.steps.append(
{
- 'layout': layout,
- 'label': 'Introduction',
- 'handler': None,
+ "layout": layout,
+ "label": "Introduction",
+ "handler": None,
},
)
@@ -233,9 +237,9 @@ def process_steps(self):
layout.align = HorizontalAlign.JUSTIFY
self.steps.append(
{
- 'layout': layout,
- 'label': handler.get_label(),
- 'handler': handler,
+ "layout": layout,
+ "label": handler.get_label(),
+ "handler": handler,
},
)
@@ -247,9 +251,9 @@ def process_steps(self):
)
self.steps.append(
{
- 'layout': layout,
- 'label': 'Summary',
- 'handler': None,
+ "layout": layout,
+ "label": "Summary",
+ "handler": None,
},
)
@@ -257,7 +261,7 @@ def _check_no_next_steps(self):
idx = self.current_step_idx + 1
while idx <= len(self.steps) - 1:
next_step = self.steps[idx]
- next_handler = next_step['handler']
+ next_handler = next_step["handler"]
if next_handler and not next_handler.is_disabled(self.answers):
return False
idx += 1
@@ -273,9 +277,8 @@ def set_buttons_labels(self):
self.buttons = [self.next_btn, self.cancel_btn]
return
- if (
- self.current_step_idx == len(self.steps) - 1
- or (self._check_no_next_steps() and not self.summary)
+ if self.current_step_idx == len(self.steps) - 1 or (
+ self._check_no_next_steps() and not self.summary
):
self.next_btn.text = self.label_finish
else:
@@ -288,31 +291,31 @@ def cancel(self):
def previous(self):
if self.current_step_idx != 0:
- self.error_messages = ''
+ self.error_messages = ""
self.current_step_idx -= 1
self.current_step = self.steps[self.current_step_idx]
- handler = self.current_step['handler']
+ handler = self.current_step["handler"]
if handler and handler.is_disabled(self.answers):
return self.previous()
- get_app().layout.focus(self.current_step['layout'])
+ get_app().layout.focus(self.current_step["layout"])
self.set_buttons_labels()
def next(self): # noqa: CCR001
if self.validate():
if self.current_step_idx < len(self.steps) - 1:
- handler = self.current_step['handler']
+ handler = self.current_step["handler"]
if handler:
self.answers.update(handler.get_answer())
self.current_step_idx += 1
self.current_step = self.steps[self.current_step_idx]
- handler = self.current_step['handler']
+ handler = self.current_step["handler"]
if handler:
if handler.is_disabled(context=self.answers):
return self.next() # noqa: B305
handler.set_context(self.answers)
if not self.summary or self.current_step != self.steps[-1]:
- get_app().layout.focus(self.current_step['layout'])
+ get_app().layout.focus(self.current_step["layout"])
else:
get_app().exit(result=True)
@@ -322,7 +325,7 @@ def fast_forward(self):
while self.current_step_idx < len(self.steps) - 1:
if self.validate():
step = self.steps[self.current_step_idx]
- handler = step['handler']
+ handler = step["handler"]
if handler and not handler.is_disabled(self.answers):
self.answers.update(handler.get_answer())
handler.set_context(self.answers)
@@ -335,15 +338,15 @@ def fast_forward(self):
def validate(self):
step = self.steps[self.current_step_idx]
- handler = step['handler']
+ handler = step["handler"]
if (
- handler
- and not handler.is_valid(self.answers)
- and not handler.is_disabled(self.answers)
+ handler
+ and not handler.is_valid(self.answers)
+ and not handler.is_disabled(self.answers)
):
- self.error_messages = ','.join(handler.errors)
+ self.error_messages = ",".join(handler.errors)
return False
- self.error_messages = ''
+ self.error_messages = ""
return True
def __pt_container__(self): # pragma: no cover
diff --git a/poetry.lock b/poetry.lock
index fb0fd67..6ed2c8b 100644
--- a/poetry.lock
+++ b/poetry.lock
@@ -1,85 +1,63 @@
-# This file is automatically @generated by Poetry and should not be changed by hand.
+# This file is automatically @generated by Poetry 1.8.5 and should not be changed by hand.
[[package]]
name = "alabaster"
-version = "0.7.12"
+version = "0.7.13"
description = "A configurable sidebar-enabled Sphinx theme"
-category = "dev"
optional = false
-python-versions = "*"
+python-versions = ">=3.6"
files = [
- {file = "alabaster-0.7.12-py2.py3-none-any.whl", hash = "sha256:446438bdcca0e05bd45ea2de1668c1d9b032e1a9154c2c259092d77031ddd359"},
- {file = "alabaster-0.7.12.tar.gz", hash = "sha256:a661d72d58e6ea8a57f7a86e37d86716863ee5e92788398526d58b26a4e4dc02"},
+ {file = "alabaster-0.7.13-py3-none-any.whl", hash = "sha256:1ee19aca801bbabb5ba3f5f258e4422dfa86f82f3e9cefb0859b283cdd7f62a3"},
+ {file = "alabaster-0.7.13.tar.gz", hash = "sha256:a27a4a084d5e690e16e01e03ad2b2e552c61a65469419b907243193de1a84ae2"},
]
[[package]]
name = "appnope"
-version = "0.1.3"
+version = "0.1.4"
description = "Disable App Nap on macOS >= 10.9"
-category = "dev"
optional = false
-python-versions = "*"
+python-versions = ">=3.6"
files = [
- {file = "appnope-0.1.3-py2.py3-none-any.whl", hash = "sha256:265a455292d0bd8a72453494fa24df5a11eb18373a60c7c0430889f22548605e"},
- {file = "appnope-0.1.3.tar.gz", hash = "sha256:02bd91c4de869fbb1e1c50aafc4098827a7a54ab2f39d9dcba6c9547ed920e24"},
+ {file = "appnope-0.1.4-py2.py3-none-any.whl", hash = "sha256:502575ee11cd7a28c0205f379b525beefebab9d161b7c964670864014ed7213c"},
+ {file = "appnope-0.1.4.tar.gz", hash = "sha256:1de3860566df9caf38f01f86f65e0e13e379af54f9e4bee1e66b48f2efffd1ee"},
]
[[package]]
name = "asttokens"
-version = "2.2.1"
+version = "3.0.0"
description = "Annotate AST trees with source code positions"
-category = "dev"
-optional = false
-python-versions = "*"
-files = [
- {file = "asttokens-2.2.1-py2.py3-none-any.whl", hash = "sha256:6b0ac9e93fb0335014d382b8fa9b3afa7df546984258005da0b9e7095b3deb1c"},
- {file = "asttokens-2.2.1.tar.gz", hash = "sha256:4622110b2a6f30b77e1473affaa97e711bc2f07d3f10848420ff1898edbe94f3"},
-]
-
-[package.dependencies]
-six = "*"
-
-[package.extras]
-test = ["astroid", "pytest"]
-
-[[package]]
-name = "attrs"
-version = "22.1.0"
-description = "Classes Without Boilerplate"
-category = "dev"
optional = false
-python-versions = ">=3.5"
+python-versions = ">=3.8"
files = [
- {file = "attrs-22.1.0-py2.py3-none-any.whl", hash = "sha256:86efa402f67bf2df34f51a335487cf46b1ec130d02b8d39fd248abfd30da551c"},
- {file = "attrs-22.1.0.tar.gz", hash = "sha256:29adc2665447e5191d0e7c568fde78b21f9672d344281d0c6e1ab085429b22b6"},
+ {file = "asttokens-3.0.0-py3-none-any.whl", hash = "sha256:e3078351a059199dd5138cb1c706e6430c05eff2ff136af5eb4790f9d28932e2"},
+ {file = "asttokens-3.0.0.tar.gz", hash = "sha256:0dcd8baa8d62b0c1d118b399b2ddba3c4aff271d0d7a9e0d4c1681c79035bbc7"},
]
[package.extras]
-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"]
-docs = ["furo", "sphinx", "sphinx-notfound-page", "zope.interface"]
-tests = ["cloudpickle", "coverage[toml] (>=5.0.2)", "hypothesis", "mypy (>=0.900,!=0.940)", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "zope.interface"]
-tests-no-zope = ["cloudpickle", "coverage[toml] (>=5.0.2)", "hypothesis", "mypy (>=0.900,!=0.940)", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins"]
+astroid = ["astroid (>=2,<4)"]
+test = ["astroid (>=2,<4)", "pytest", "pytest-cov", "pytest-xdist"]
[[package]]
name = "babel"
-version = "2.11.0"
+version = "2.16.0"
description = "Internationalization utilities"
-category = "dev"
optional = false
-python-versions = ">=3.6"
+python-versions = ">=3.8"
files = [
- {file = "Babel-2.11.0-py3-none-any.whl", hash = "sha256:1ad3eca1c885218f6dce2ab67291178944f810a10a9b5f3cb8382a5a232b64fe"},
- {file = "Babel-2.11.0.tar.gz", hash = "sha256:5ef4b3226b0180dedded4229651c8b0e1a3a6a2837d45a073272f313e4cf97f6"},
+ {file = "babel-2.16.0-py3-none-any.whl", hash = "sha256:368b5b98b37c06b7daf6696391c3240c938b37767d4584413e8438c5c435fa8b"},
+ {file = "babel-2.16.0.tar.gz", hash = "sha256:d1f3554ca26605fe173f3de0c65f750f5a42f924499bf134de6423582298e316"},
]
[package.dependencies]
-pytz = ">=2015.7"
+pytz = {version = ">=2015.7", markers = "python_version < \"3.9\""}
+
+[package.extras]
+dev = ["freezegun (>=1.0,<2.0)", "pytest (>=6.0)", "pytest-cov"]
[[package]]
name = "backcall"
version = "0.2.0"
description = "Specifications for callback functions passed in to an API"
-category = "dev"
optional = false
python-versions = "*"
files = [
@@ -91,7 +69,6 @@ files = [
name = "backports-zoneinfo"
version = "0.2.1"
description = "Backport of the standard library zoneinfo module"
-category = "main"
optional = false
python-versions = ">=3.6"
files = [
@@ -118,50 +95,133 @@ tzdata = ["tzdata"]
[[package]]
name = "certifi"
-version = "2022.9.24"
+version = "2024.8.30"
description = "Python package for providing Mozilla's CA Bundle."
-category = "dev"
optional = false
python-versions = ">=3.6"
files = [
- {file = "certifi-2022.9.24-py3-none-any.whl", hash = "sha256:90c1a32f1d68f940488354e36370f6cca89f0f106db09518524c88d6ed83f382"},
- {file = "certifi-2022.9.24.tar.gz", hash = "sha256:0d9c601124e5a6ba9712dbc60d9c53c21e34f5f641fe83002317394311bdce14"},
+ {file = "certifi-2024.8.30-py3-none-any.whl", hash = "sha256:922820b53db7a7257ffbda3f597266d435245903d80737e34f8a45ff3e3230d8"},
+ {file = "certifi-2024.8.30.tar.gz", hash = "sha256:bec941d2aa8195e248a60b31ff9f0558284cf01a52591ceda73ea9afffd69fd9"},
]
[[package]]
name = "charset-normalizer"
-version = "2.1.1"
+version = "3.4.0"
description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet."
-category = "dev"
-optional = false
-python-versions = ">=3.6.0"
-files = [
- {file = "charset-normalizer-2.1.1.tar.gz", hash = "sha256:5a3d016c7c547f69d6f81fb0db9449ce888b418b5b9952cc5e6e66843e9dd845"},
- {file = "charset_normalizer-2.1.1-py3-none-any.whl", hash = "sha256:83e9a75d1911279afd89352c68b45348559d1fc0506b054b346651b5e7fee29f"},
-]
-
-[package.extras]
-unicode-backport = ["unicodedata2"]
-
-[[package]]
-name = "cognitive-complexity"
-version = "1.3.0"
-description = "Library to calculate Python functions cognitive complexity via code"
-category = "dev"
optional = false
-python-versions = ">=3.6"
-files = [
- {file = "cognitive_complexity-1.3.0.tar.gz", hash = "sha256:a0cfbd47dee0b19f4056f892389f501694b205c3af69fb703cc744541e03dde5"},
+python-versions = ">=3.7.0"
+files = [
+ {file = "charset_normalizer-3.4.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:4f9fc98dad6c2eaa32fc3af1417d95b5e3d08aff968df0cd320066def971f9a6"},
+ {file = "charset_normalizer-3.4.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:0de7b687289d3c1b3e8660d0741874abe7888100efe14bd0f9fd7141bcbda92b"},
+ {file = "charset_normalizer-3.4.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:5ed2e36c3e9b4f21dd9422f6893dec0abf2cca553af509b10cd630f878d3eb99"},
+ {file = "charset_normalizer-3.4.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:40d3ff7fc90b98c637bda91c89d51264a3dcf210cade3a2c6f838c7268d7a4ca"},
+ {file = "charset_normalizer-3.4.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1110e22af8ca26b90bd6364fe4c763329b0ebf1ee213ba32b68c73de5752323d"},
+ {file = "charset_normalizer-3.4.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:86f4e8cca779080f66ff4f191a685ced73d2f72d50216f7112185dc02b90b9b7"},
+ {file = "charset_normalizer-3.4.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7f683ddc7eedd742e2889d2bfb96d69573fde1d92fcb811979cdb7165bb9c7d3"},
+ {file = "charset_normalizer-3.4.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:27623ba66c183eca01bf9ff833875b459cad267aeeb044477fedac35e19ba907"},
+ {file = "charset_normalizer-3.4.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:f606a1881d2663630ea5b8ce2efe2111740df4b687bd78b34a8131baa007f79b"},
+ {file = "charset_normalizer-3.4.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:0b309d1747110feb25d7ed6b01afdec269c647d382c857ef4663bbe6ad95a912"},
+ {file = "charset_normalizer-3.4.0-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:136815f06a3ae311fae551c3df1f998a1ebd01ddd424aa5603a4336997629e95"},
+ {file = "charset_normalizer-3.4.0-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:14215b71a762336254351b00ec720a8e85cada43b987da5a042e4ce3e82bd68e"},
+ {file = "charset_normalizer-3.4.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:79983512b108e4a164b9c8d34de3992f76d48cadc9554c9e60b43f308988aabe"},
+ {file = "charset_normalizer-3.4.0-cp310-cp310-win32.whl", hash = "sha256:c94057af19bc953643a33581844649a7fdab902624d2eb739738a30e2b3e60fc"},
+ {file = "charset_normalizer-3.4.0-cp310-cp310-win_amd64.whl", hash = "sha256:55f56e2ebd4e3bc50442fbc0888c9d8c94e4e06a933804e2af3e89e2f9c1c749"},
+ {file = "charset_normalizer-3.4.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:0d99dd8ff461990f12d6e42c7347fd9ab2532fb70e9621ba520f9e8637161d7c"},
+ {file = "charset_normalizer-3.4.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:c57516e58fd17d03ebe67e181a4e4e2ccab1168f8c2976c6a334d4f819fe5944"},
+ {file = "charset_normalizer-3.4.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:6dba5d19c4dfab08e58d5b36304b3f92f3bd5d42c1a3fa37b5ba5cdf6dfcbcee"},
+ {file = "charset_normalizer-3.4.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bf4475b82be41b07cc5e5ff94810e6a01f276e37c2d55571e3fe175e467a1a1c"},
+ {file = "charset_normalizer-3.4.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ce031db0408e487fd2775d745ce30a7cd2923667cf3b69d48d219f1d8f5ddeb6"},
+ {file = "charset_normalizer-3.4.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8ff4e7cdfdb1ab5698e675ca622e72d58a6fa2a8aa58195de0c0061288e6e3ea"},
+ {file = "charset_normalizer-3.4.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3710a9751938947e6327ea9f3ea6332a09bf0ba0c09cae9cb1f250bd1f1549bc"},
+ {file = "charset_normalizer-3.4.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:82357d85de703176b5587dbe6ade8ff67f9f69a41c0733cf2425378b49954de5"},
+ {file = "charset_normalizer-3.4.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:47334db71978b23ebcf3c0f9f5ee98b8d65992b65c9c4f2d34c2eaf5bcaf0594"},
+ {file = "charset_normalizer-3.4.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:8ce7fd6767a1cc5a92a639b391891bf1c268b03ec7e021c7d6d902285259685c"},
+ {file = "charset_normalizer-3.4.0-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:f1a2f519ae173b5b6a2c9d5fa3116ce16e48b3462c8b96dfdded11055e3d6365"},
+ {file = "charset_normalizer-3.4.0-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:63bc5c4ae26e4bc6be6469943b8253c0fd4e4186c43ad46e713ea61a0ba49129"},
+ {file = "charset_normalizer-3.4.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:bcb4f8ea87d03bc51ad04add8ceaf9b0f085ac045ab4d74e73bbc2dc033f0236"},
+ {file = "charset_normalizer-3.4.0-cp311-cp311-win32.whl", hash = "sha256:9ae4ef0b3f6b41bad6366fb0ea4fc1d7ed051528e113a60fa2a65a9abb5b1d99"},
+ {file = "charset_normalizer-3.4.0-cp311-cp311-win_amd64.whl", hash = "sha256:cee4373f4d3ad28f1ab6290684d8e2ebdb9e7a1b74fdc39e4c211995f77bec27"},
+ {file = "charset_normalizer-3.4.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:0713f3adb9d03d49d365b70b84775d0a0d18e4ab08d12bc46baa6132ba78aaf6"},
+ {file = "charset_normalizer-3.4.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:de7376c29d95d6719048c194a9cf1a1b0393fbe8488a22008610b0361d834ecf"},
+ {file = "charset_normalizer-3.4.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:4a51b48f42d9358460b78725283f04bddaf44a9358197b889657deba38f329db"},
+ {file = "charset_normalizer-3.4.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b295729485b06c1a0683af02a9e42d2caa9db04a373dc38a6a58cdd1e8abddf1"},
+ {file = "charset_normalizer-3.4.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ee803480535c44e7f5ad00788526da7d85525cfefaf8acf8ab9a310000be4b03"},
+ {file = "charset_normalizer-3.4.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3d59d125ffbd6d552765510e3f31ed75ebac2c7470c7274195b9161a32350284"},
+ {file = "charset_normalizer-3.4.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8cda06946eac330cbe6598f77bb54e690b4ca93f593dee1568ad22b04f347c15"},
+ {file = "charset_normalizer-3.4.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:07afec21bbbbf8a5cc3651aa96b980afe2526e7f048fdfb7f1014d84acc8b6d8"},
+ {file = "charset_normalizer-3.4.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:6b40e8d38afe634559e398cc32b1472f376a4099c75fe6299ae607e404c033b2"},
+ {file = "charset_normalizer-3.4.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:b8dcd239c743aa2f9c22ce674a145e0a25cb1566c495928440a181ca1ccf6719"},
+ {file = "charset_normalizer-3.4.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:84450ba661fb96e9fd67629b93d2941c871ca86fc38d835d19d4225ff946a631"},
+ {file = "charset_normalizer-3.4.0-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:44aeb140295a2f0659e113b31cfe92c9061622cadbc9e2a2f7b8ef6b1e29ef4b"},
+ {file = "charset_normalizer-3.4.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:1db4e7fefefd0f548d73e2e2e041f9df5c59e178b4c72fbac4cc6f535cfb1565"},
+ {file = "charset_normalizer-3.4.0-cp312-cp312-win32.whl", hash = "sha256:5726cf76c982532c1863fb64d8c6dd0e4c90b6ece9feb06c9f202417a31f7dd7"},
+ {file = "charset_normalizer-3.4.0-cp312-cp312-win_amd64.whl", hash = "sha256:b197e7094f232959f8f20541ead1d9862ac5ebea1d58e9849c1bf979255dfac9"},
+ {file = "charset_normalizer-3.4.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:dd4eda173a9fcccb5f2e2bd2a9f423d180194b1bf17cf59e3269899235b2a114"},
+ {file = "charset_normalizer-3.4.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:e9e3c4c9e1ed40ea53acf11e2a386383c3304212c965773704e4603d589343ed"},
+ {file = "charset_normalizer-3.4.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:92a7e36b000bf022ef3dbb9c46bfe2d52c047d5e3f3343f43204263c5addc250"},
+ {file = "charset_normalizer-3.4.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:54b6a92d009cbe2fb11054ba694bc9e284dad30a26757b1e372a1fdddaf21920"},
+ {file = "charset_normalizer-3.4.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1ffd9493de4c922f2a38c2bf62b831dcec90ac673ed1ca182fe11b4d8e9f2a64"},
+ {file = "charset_normalizer-3.4.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:35c404d74c2926d0287fbd63ed5d27eb911eb9e4a3bb2c6d294f3cfd4a9e0c23"},
+ {file = "charset_normalizer-3.4.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4796efc4faf6b53a18e3d46343535caed491776a22af773f366534056c4e1fbc"},
+ {file = "charset_normalizer-3.4.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e7fdd52961feb4c96507aa649550ec2a0d527c086d284749b2f582f2d40a2e0d"},
+ {file = "charset_normalizer-3.4.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:92db3c28b5b2a273346bebb24857fda45601aef6ae1c011c0a997106581e8a88"},
+ {file = "charset_normalizer-3.4.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:ab973df98fc99ab39080bfb0eb3a925181454d7c3ac8a1e695fddfae696d9e90"},
+ {file = "charset_normalizer-3.4.0-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:4b67fdab07fdd3c10bb21edab3cbfe8cf5696f453afce75d815d9d7223fbe88b"},
+ {file = "charset_normalizer-3.4.0-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:aa41e526a5d4a9dfcfbab0716c7e8a1b215abd3f3df5a45cf18a12721d31cb5d"},
+ {file = "charset_normalizer-3.4.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:ffc519621dce0c767e96b9c53f09c5d215578e10b02c285809f76509a3931482"},
+ {file = "charset_normalizer-3.4.0-cp313-cp313-win32.whl", hash = "sha256:f19c1585933c82098c2a520f8ec1227f20e339e33aca8fa6f956f6691b784e67"},
+ {file = "charset_normalizer-3.4.0-cp313-cp313-win_amd64.whl", hash = "sha256:707b82d19e65c9bd28b81dde95249b07bf9f5b90ebe1ef17d9b57473f8a64b7b"},
+ {file = "charset_normalizer-3.4.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:dbe03226baf438ac4fda9e2d0715022fd579cb641c4cf639fa40d53b2fe6f3e2"},
+ {file = "charset_normalizer-3.4.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dd9a8bd8900e65504a305bf8ae6fa9fbc66de94178c420791d0293702fce2df7"},
+ {file = "charset_normalizer-3.4.0-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b8831399554b92b72af5932cdbbd4ddc55c55f631bb13ff8fe4e6536a06c5c51"},
+ {file = "charset_normalizer-3.4.0-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a14969b8691f7998e74663b77b4c36c0337cb1df552da83d5c9004a93afdb574"},
+ {file = "charset_normalizer-3.4.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dcaf7c1524c0542ee2fc82cc8ec337f7a9f7edee2532421ab200d2b920fc97cf"},
+ {file = "charset_normalizer-3.4.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:425c5f215d0eecee9a56cdb703203dda90423247421bf0d67125add85d0c4455"},
+ {file = "charset_normalizer-3.4.0-cp37-cp37m-musllinux_1_2_aarch64.whl", hash = "sha256:d5b054862739d276e09928de37c79ddeec42a6e1bfc55863be96a36ba22926f6"},
+ {file = "charset_normalizer-3.4.0-cp37-cp37m-musllinux_1_2_i686.whl", hash = "sha256:f3e73a4255342d4eb26ef6df01e3962e73aa29baa3124a8e824c5d3364a65748"},
+ {file = "charset_normalizer-3.4.0-cp37-cp37m-musllinux_1_2_ppc64le.whl", hash = "sha256:2f6c34da58ea9c1a9515621f4d9ac379871a8f21168ba1b5e09d74250de5ad62"},
+ {file = "charset_normalizer-3.4.0-cp37-cp37m-musllinux_1_2_s390x.whl", hash = "sha256:f09cb5a7bbe1ecae6e87901a2eb23e0256bb524a79ccc53eb0b7629fbe7677c4"},
+ {file = "charset_normalizer-3.4.0-cp37-cp37m-musllinux_1_2_x86_64.whl", hash = "sha256:0099d79bdfcf5c1f0c2c72f91516702ebf8b0b8ddd8905f97a8aecf49712c621"},
+ {file = "charset_normalizer-3.4.0-cp37-cp37m-win32.whl", hash = "sha256:9c98230f5042f4945f957d006edccc2af1e03ed5e37ce7c373f00a5a4daa6149"},
+ {file = "charset_normalizer-3.4.0-cp37-cp37m-win_amd64.whl", hash = "sha256:62f60aebecfc7f4b82e3f639a7d1433a20ec32824db2199a11ad4f5e146ef5ee"},
+ {file = "charset_normalizer-3.4.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:af73657b7a68211996527dbfeffbb0864e043d270580c5aef06dc4b659a4b578"},
+ {file = "charset_normalizer-3.4.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:cab5d0b79d987c67f3b9e9c53f54a61360422a5a0bc075f43cab5621d530c3b6"},
+ {file = "charset_normalizer-3.4.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:9289fd5dddcf57bab41d044f1756550f9e7cf0c8e373b8cdf0ce8773dc4bd417"},
+ {file = "charset_normalizer-3.4.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6b493a043635eb376e50eedf7818f2f322eabbaa974e948bd8bdd29eb7ef2a51"},
+ {file = "charset_normalizer-3.4.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9fa2566ca27d67c86569e8c85297aaf413ffab85a8960500f12ea34ff98e4c41"},
+ {file = "charset_normalizer-3.4.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a8e538f46104c815be19c975572d74afb53f29650ea2025bbfaef359d2de2f7f"},
+ {file = "charset_normalizer-3.4.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6fd30dc99682dc2c603c2b315bded2799019cea829f8bf57dc6b61efde6611c8"},
+ {file = "charset_normalizer-3.4.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2006769bd1640bdf4d5641c69a3d63b71b81445473cac5ded39740a226fa88ab"},
+ {file = "charset_normalizer-3.4.0-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:dc15e99b2d8a656f8e666854404f1ba54765871104e50c8e9813af8a7db07f12"},
+ {file = "charset_normalizer-3.4.0-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:ab2e5bef076f5a235c3774b4f4028a680432cded7cad37bba0fd90d64b187d19"},
+ {file = "charset_normalizer-3.4.0-cp38-cp38-musllinux_1_2_ppc64le.whl", hash = "sha256:4ec9dd88a5b71abfc74e9df5ebe7921c35cbb3b641181a531ca65cdb5e8e4dea"},
+ {file = "charset_normalizer-3.4.0-cp38-cp38-musllinux_1_2_s390x.whl", hash = "sha256:43193c5cda5d612f247172016c4bb71251c784d7a4d9314677186a838ad34858"},
+ {file = "charset_normalizer-3.4.0-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:aa693779a8b50cd97570e5a0f343538a8dbd3e496fa5dcb87e29406ad0299654"},
+ {file = "charset_normalizer-3.4.0-cp38-cp38-win32.whl", hash = "sha256:7706f5850360ac01d80c89bcef1640683cc12ed87f42579dab6c5d3ed6888613"},
+ {file = "charset_normalizer-3.4.0-cp38-cp38-win_amd64.whl", hash = "sha256:c3e446d253bd88f6377260d07c895816ebf33ffffd56c1c792b13bff9c3e1ade"},
+ {file = "charset_normalizer-3.4.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:980b4f289d1d90ca5efcf07958d3eb38ed9c0b7676bf2831a54d4f66f9c27dfa"},
+ {file = "charset_normalizer-3.4.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:f28f891ccd15c514a0981f3b9db9aa23d62fe1a99997512b0491d2ed323d229a"},
+ {file = "charset_normalizer-3.4.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:a8aacce6e2e1edcb6ac625fb0f8c3a9570ccc7bfba1f63419b3769ccf6a00ed0"},
+ {file = "charset_normalizer-3.4.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bd7af3717683bea4c87acd8c0d3d5b44d56120b26fd3f8a692bdd2d5260c620a"},
+ {file = "charset_normalizer-3.4.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5ff2ed8194587faf56555927b3aa10e6fb69d931e33953943bc4f837dfee2242"},
+ {file = "charset_normalizer-3.4.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e91f541a85298cf35433bf66f3fab2a4a2cff05c127eeca4af174f6d497f0d4b"},
+ {file = "charset_normalizer-3.4.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:309a7de0a0ff3040acaebb35ec45d18db4b28232f21998851cfa709eeff49d62"},
+ {file = "charset_normalizer-3.4.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:285e96d9d53422efc0d7a17c60e59f37fbf3dfa942073f666db4ac71e8d726d0"},
+ {file = "charset_normalizer-3.4.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:5d447056e2ca60382d460a604b6302d8db69476fd2015c81e7c35417cfabe4cd"},
+ {file = "charset_normalizer-3.4.0-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:20587d20f557fe189b7947d8e7ec5afa110ccf72a3128d61a2a387c3313f46be"},
+ {file = "charset_normalizer-3.4.0-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:130272c698667a982a5d0e626851ceff662565379baf0ff2cc58067b81d4f11d"},
+ {file = "charset_normalizer-3.4.0-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:ab22fbd9765e6954bc0bcff24c25ff71dcbfdb185fcdaca49e81bac68fe724d3"},
+ {file = "charset_normalizer-3.4.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:7782afc9b6b42200f7362858f9e73b1f8316afb276d316336c0ec3bd73312742"},
+ {file = "charset_normalizer-3.4.0-cp39-cp39-win32.whl", hash = "sha256:2de62e8801ddfff069cd5c504ce3bc9672b23266597d4e4f50eda28846c322f2"},
+ {file = "charset_normalizer-3.4.0-cp39-cp39-win_amd64.whl", hash = "sha256:95c3c157765b031331dd4db3c775e58deaee050a3042fcad72cbc4189d7c8dca"},
+ {file = "charset_normalizer-3.4.0-py3-none-any.whl", hash = "sha256:fe9f97feb71aa9896b81973a7bbada8c49501dc73e58a10fcef6663af95e5079"},
+ {file = "charset_normalizer-3.4.0.tar.gz", hash = "sha256:223217c3d4f82c3ac5e29032b3f1c2eb0fb591b72161f86d93f5719079dae93e"},
]
-[package.dependencies]
-setuptools = "*"
-
[[package]]
name = "colorama"
version = "0.4.6"
description = "Cross-platform colored terminal text."
-category = "dev"
optional = false
python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7"
files = [
@@ -173,7 +233,6 @@ files = [
name = "coverage"
version = "6.5.0"
description = "Code coverage measurement for Python"
-category = "dev"
optional = false
python-versions = ">=3.7"
files = [
@@ -239,7 +298,6 @@ toml = ["tomli"]
name = "decorator"
version = "5.1.1"
description = "Decorators for Humans"
-category = "main"
optional = false
python-versions = ">=3.5"
files = [
@@ -249,26 +307,24 @@ files = [
[[package]]
name = "docutils"
-version = "0.17.1"
+version = "0.18.1"
description = "Docutils -- Python Documentation Utilities"
-category = "dev"
optional = false
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
files = [
- {file = "docutils-0.17.1-py2.py3-none-any.whl", hash = "sha256:cf316c8370a737a022b72b56874f6602acf974a37a9fba42ec2876387549fc61"},
- {file = "docutils-0.17.1.tar.gz", hash = "sha256:686577d2e4c32380bb50cbb22f575ed742d58168cee37e99117a854bcd88f125"},
+ {file = "docutils-0.18.1-py2.py3-none-any.whl", hash = "sha256:23010f129180089fbcd3bc08cfefccb3b890b0050e1ca00c867036e9d161b98c"},
+ {file = "docutils-0.18.1.tar.gz", hash = "sha256:679987caf361a7539d76e584cbeddc311e3aee937877c87346f31debc63e9d06"},
]
[[package]]
name = "exceptiongroup"
-version = "1.0.4"
+version = "1.2.2"
description = "Backport of PEP 654 (exception groups)"
-category = "dev"
optional = false
python-versions = ">=3.7"
files = [
- {file = "exceptiongroup-1.0.4-py3-none-any.whl", hash = "sha256:542adf9dea4055530d6e1279602fa5cb11dab2395fa650b8674eaec35fc4a828"},
- {file = "exceptiongroup-1.0.4.tar.gz", hash = "sha256:bd14967b79cd9bdb54d97323216f8fdf533e278df937aa2a90089e7d6e06e5ec"},
+ {file = "exceptiongroup-1.2.2-py3-none-any.whl", hash = "sha256:3111b9d131c238bec2f8f516e123e14ba243563fb135d3fe885990585aa7795b"},
+ {file = "exceptiongroup-1.2.2.tar.gz", hash = "sha256:47c2edf7c6738fafb49fd34290706d1a1a2f4d1c6df275526b62cbb4aa5393cc"},
]
[package.extras]
@@ -276,177 +332,81 @@ test = ["pytest (>=6)"]
[[package]]
name = "executing"
-version = "1.2.0"
+version = "2.1.0"
description = "Get the currently executing AST node of a frame, and other information"
-category = "dev"
-optional = false
-python-versions = "*"
-files = [
- {file = "executing-1.2.0-py2.py3-none-any.whl", hash = "sha256:0314a69e37426e3608aada02473b4161d4caf5a4b244d1d0c48072b8fee7bacc"},
- {file = "executing-1.2.0.tar.gz", hash = "sha256:19da64c18d2d851112f09c287f8d3dbbdf725ab0e569077efb6cdcbd3497c107"},
-]
-
-[package.extras]
-tests = ["asttokens", "littleutils", "pytest", "rich"]
-
-[[package]]
-name = "flake8"
-version = "3.9.2"
-description = "the modular source code checker: pep8 pyflakes and co"
-category = "dev"
-optional = false
-python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7"
-files = [
- {file = "flake8-3.9.2-py2.py3-none-any.whl", hash = "sha256:bf8fd333346d844f616e8d47905ef3a3384edae6b4e9beb0c5101e25e3110907"},
- {file = "flake8-3.9.2.tar.gz", hash = "sha256:07528381786f2a6237b061f6e96610a4167b226cb926e2aa2b6b1d78057c576b"},
-]
-
-[package.dependencies]
-mccabe = ">=0.6.0,<0.7.0"
-pycodestyle = ">=2.7.0,<2.8.0"
-pyflakes = ">=2.3.0,<2.4.0"
-
-[[package]]
-name = "flake8-broken-line"
-version = "0.6.0"
-description = "Flake8 plugin to forbid backslashes for line breaks"
-category = "dev"
-optional = false
-python-versions = ">=3.7,<4.0"
-files = [
- {file = "flake8-broken-line-0.6.0.tar.gz", hash = "sha256:a02268f11a18837c83c59013a36cc00fee9e17a042745cc0c9895f1c9f6acc16"},
- {file = "flake8_broken_line-0.6.0-py3-none-any.whl", hash = "sha256:c0ab336ff7de228dbffbe56d67b3615bb21fb15f3ed0604fa7bdf9feb72d7d88"},
-]
-
-[package.dependencies]
-flake8 = ">=3.5,<6"
-
-[[package]]
-name = "flake8-bugbear"
-version = "22.12.6"
-description = "A plugin for flake8 finding likely bugs and design problems in your program. Contains warnings that don't belong in pyflakes and pycodestyle."
-category = "dev"
optional = false
-python-versions = ">=3.7"
+python-versions = ">=3.8"
files = [
- {file = "flake8-bugbear-22.12.6.tar.gz", hash = "sha256:4cdb2c06e229971104443ae293e75e64c6107798229202fbe4f4091427a30ac0"},
- {file = "flake8_bugbear-22.12.6-py3-none-any.whl", hash = "sha256:b69a510634f8a9c298dfda2b18a8036455e6b19ecac4fe582e4d7a0abfa50a30"},
+ {file = "executing-2.1.0-py2.py3-none-any.whl", hash = "sha256:8d63781349375b5ebccc3142f4b30350c0cd9c79f921cde38be2be4637e98eaf"},
+ {file = "executing-2.1.0.tar.gz", hash = "sha256:8ea27ddd260da8150fa5a708269c4a10e76161e2496ec3e587da9e3c0fe4b9ab"},
]
-[package.dependencies]
-attrs = ">=19.2.0"
-flake8 = ">=3.0.0"
-
[package.extras]
-dev = ["coverage", "hypothesis", "hypothesmith (>=0.2)", "pre-commit", "tox"]
+tests = ["asttokens (>=2.1.0)", "coverage", "coverage-enable-subprocess", "ipython", "littleutils", "pytest", "rich"]
[[package]]
-name = "flake8-cognitive-complexity"
-version = "0.1.0"
-description = "An extension for flake8 that validates cognitive functions complexity"
-category = "dev"
+name = "idna"
+version = "3.10"
+description = "Internationalized Domain Names in Applications (IDNA)"
optional = false
python-versions = ">=3.6"
files = [
- {file = "flake8_cognitive_complexity-0.1.0.tar.gz", hash = "sha256:f202df054e4f6ff182b659c261922b9c684628a47beb19cb0973c50d6a7831c1"},
-]
-
-[package.dependencies]
-cognitive_complexity = "*"
-setuptools = "*"
-
-[[package]]
-name = "flake8-commas"
-version = "2.0.0"
-description = "Flake8 lint for trailing commas."
-category = "dev"
-optional = false
-python-versions = "*"
-files = [
- {file = "flake8-commas-2.0.0.tar.gz", hash = "sha256:d3005899466f51380387df7151fb59afec666a0f4f4a2c6a8995b975de0f44b7"},
- {file = "flake8_commas-2.0.0-py2.py3-none-any.whl", hash = "sha256:ee2141a3495ef9789a3894ed8802d03eff1eaaf98ce6d8653a7c573ef101935e"},
+ {file = "idna-3.10-py3-none-any.whl", hash = "sha256:946d195a0d259cbba61165e88e65941f16e9b36ea6ddb97f00452bae8b1287d3"},
+ {file = "idna-3.10.tar.gz", hash = "sha256:12f65c9b470abda6dc35cf8e63cc574b1c52b11df2c86030af0ac09b01b13ea9"},
]
-[package.dependencies]
-flake8 = ">=2,<4.0.0"
+[package.extras]
+all = ["flake8 (>=7.1.1)", "mypy (>=1.11.2)", "pytest (>=8.3.2)", "ruff (>=0.6.2)"]
[[package]]
-name = "flake8-future-import"
-version = "0.4.7"
-description = "__future__ import checker, plugin for flake8"
-category = "dev"
+name = "imagesize"
+version = "1.4.1"
+description = "Getting image size from png/jpeg/jpeg2000/gif file"
optional = false
-python-versions = ">=3.6"
+python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
files = [
- {file = "flake8-future-import-0.4.7.tar.gz", hash = "sha256:ed826cca28fd4b55c486d69c4bfb32e9a052efc66714bf22bf471f50ecf8e0de"},
- {file = "flake8_future_import-0.4.7-py2.py3-none-any.whl", hash = "sha256:7ecb1b89f5e026afb0cfdb8642d150bf56efbb6fb86a713ea4568398142f47ae"},
+ {file = "imagesize-1.4.1-py2.py3-none-any.whl", hash = "sha256:0d8d18d08f840c19d0ee7ca1fd82490fdc3729b7ac93f49870406ddde8ef8d8b"},
+ {file = "imagesize-1.4.1.tar.gz", hash = "sha256:69150444affb9cb0d5cc5a92b3676f0b2fb7cd9ae39e947a5e11a36b4497cd4a"},
]
-[package.dependencies]
-flake8 = "*"
-
[[package]]
-name = "flake8-import-order"
-version = "0.18.2"
-description = "Flake8 and pylama plugin that checks the ordering of import statements."
-category = "dev"
+name = "importlib-metadata"
+version = "1.4.0"
+description = "Read metadata from Python packages"
optional = false
-python-versions = "*"
+python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7"
files = [
- {file = "flake8-import-order-0.18.2.tar.gz", hash = "sha256:e23941f892da3e0c09d711babbb0c73bc735242e9b216b726616758a920d900e"},
- {file = "flake8_import_order-0.18.2-py2.py3-none-any.whl", hash = "sha256:82ed59f1083b629b030ee9d3928d9e06b6213eb196fe745b3a7d4af2168130df"},
+ {file = "importlib_metadata-1.4.0-py2.py3-none-any.whl", hash = "sha256:bdd9b7c397c273bcc9a11d6629a38487cd07154fa255a467bf704cd2c258e359"},
+ {file = "importlib_metadata-1.4.0.tar.gz", hash = "sha256:f17c015735e1a88296994c0697ecea7e11db24290941983b08c9feb30921e6d8"},
]
[package.dependencies]
-pycodestyle = "*"
-setuptools = "*"
-
-[[package]]
-name = "idna"
-version = "3.4"
-description = "Internationalized Domain Names in Applications (IDNA)"
-category = "dev"
-optional = false
-python-versions = ">=3.5"
-files = [
- {file = "idna-3.4-py3-none-any.whl", hash = "sha256:90b77e79eaa3eba6de819a0c442c0b4ceefc341a7a2ab77d7562bf49f425c5c2"},
- {file = "idna-3.4.tar.gz", hash = "sha256:814f528e8dead7d329833b91c5faa87d60bf71824cd12a7530b5526063d02cb4"},
-]
+zipp = ">=0.5"
-[[package]]
-name = "imagesize"
-version = "1.4.1"
-description = "Getting image size from png/jpeg/jpeg2000/gif file"
-category = "dev"
-optional = false
-python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
-files = [
- {file = "imagesize-1.4.1-py2.py3-none-any.whl", hash = "sha256:0d8d18d08f840c19d0ee7ca1fd82490fdc3729b7ac93f49870406ddde8ef8d8b"},
- {file = "imagesize-1.4.1.tar.gz", hash = "sha256:69150444affb9cb0d5cc5a92b3676f0b2fb7cd9ae39e947a5e11a36b4497cd4a"},
-]
+[package.extras]
+docs = ["rst.linker", "sphinx"]
+testing = ["importlib-resources", "packaging"]
[[package]]
name = "iniconfig"
-version = "1.1.1"
-description = "iniconfig: brain-dead simple config-ini parsing"
-category = "dev"
+version = "2.0.0"
+description = "brain-dead simple config-ini parsing"
optional = false
-python-versions = "*"
+python-versions = ">=3.7"
files = [
- {file = "iniconfig-1.1.1-py2.py3-none-any.whl", hash = "sha256:011e24c64b7f47f6ebd835bb12a743f2fbe9a26d4cecaa7f53bc4f35ee9da8b3"},
- {file = "iniconfig-1.1.1.tar.gz", hash = "sha256:bc3af051d7d14b2ee5ef9969666def0cd1a000e121eaea580d4a313df4b37f32"},
+ {file = "iniconfig-2.0.0-py3-none-any.whl", hash = "sha256:b6a85871a79d2e3b22d2d1b94ac2824226a63c6b741c88f7ae975f18b6778374"},
+ {file = "iniconfig-2.0.0.tar.gz", hash = "sha256:2d91e135bf72d31a410b17c16da610a82cb55f6b0477d1a902134b24a455b8b3"},
]
[[package]]
name = "ipython"
-version = "8.10.0"
+version = "8.12.3"
description = "IPython: Productive Interactive Computing"
-category = "dev"
optional = false
python-versions = ">=3.8"
files = [
- {file = "ipython-8.10.0-py3-none-any.whl", hash = "sha256:b38c31e8fc7eff642fc7c597061fff462537cf2314e3225a19c906b7b0d8a345"},
- {file = "ipython-8.10.0.tar.gz", hash = "sha256:b13a1d6c1f5818bd388db53b7107d17454129a70de2b87481d555daede5eb49e"},
+ {file = "ipython-8.12.3-py3-none-any.whl", hash = "sha256:b0340d46a933d27c657b211a329d0be23793c36595acf9e6ef4164bc01a1804c"},
+ {file = "ipython-8.12.3.tar.gz", hash = "sha256:3910c4b54543c2ad73d06579aa771041b7d5707b033bd488669b4cf544e3b363"},
]
[package.dependencies]
@@ -458,10 +418,11 @@ jedi = ">=0.16"
matplotlib-inline = "*"
pexpect = {version = ">4.3", markers = "sys_platform != \"win32\""}
pickleshare = "*"
-prompt-toolkit = ">=3.0.30,<3.1.0"
+prompt-toolkit = ">=3.0.30,<3.0.37 || >3.0.37,<3.1.0"
pygments = ">=2.4.0"
stack-data = "*"
traitlets = ">=5"
+typing-extensions = {version = "*", markers = "python_version < \"3.10\""}
[package.extras]
all = ["black", "curio", "docrepr", "ipykernel", "ipyparallel", "ipywidgets", "matplotlib", "matplotlib (!=3.2.0)", "nbconvert", "nbformat", "notebook", "numpy (>=1.21)", "pandas", "pytest (<7)", "pytest (<7.1)", "pytest-asyncio", "qtconsole", "setuptools (>=18.5)", "sphinx (>=1.3)", "sphinx-rtd-theme", "stack-data", "testpath", "trio", "typing-extensions"]
@@ -478,34 +439,32 @@ test-extra = ["curio", "matplotlib (!=3.2.0)", "nbformat", "numpy (>=1.21)", "pa
[[package]]
name = "jedi"
-version = "0.18.2"
+version = "0.19.2"
description = "An autocompletion tool for Python that can be used for text editors."
-category = "dev"
optional = false
python-versions = ">=3.6"
files = [
- {file = "jedi-0.18.2-py2.py3-none-any.whl", hash = "sha256:203c1fd9d969ab8f2119ec0a3342e0b49910045abe6af0a3ae83a5764d54639e"},
- {file = "jedi-0.18.2.tar.gz", hash = "sha256:bae794c30d07f6d910d32a7048af09b5a39ed740918da923c6b780790ebac612"},
+ {file = "jedi-0.19.2-py2.py3-none-any.whl", hash = "sha256:a8ef22bde8490f57fe5c7681a3c83cb58874daf72b4784de3cce5b6ef6edb5b9"},
+ {file = "jedi-0.19.2.tar.gz", hash = "sha256:4770dc3de41bde3966b02eb84fbcf557fb33cce26ad23da12c742fb50ecb11f0"},
]
[package.dependencies]
-parso = ">=0.8.0,<0.9.0"
+parso = ">=0.8.4,<0.9.0"
[package.extras]
docs = ["Jinja2 (==2.11.3)", "MarkupSafe (==1.1.1)", "Pygments (==2.8.1)", "alabaster (==0.7.12)", "babel (==2.9.1)", "chardet (==4.0.0)", "commonmark (==0.8.1)", "docutils (==0.17.1)", "future (==0.18.2)", "idna (==2.10)", "imagesize (==1.2.0)", "mock (==1.0.1)", "packaging (==20.9)", "pyparsing (==2.4.7)", "pytz (==2021.1)", "readthedocs-sphinx-ext (==2.1.4)", "recommonmark (==0.5.0)", "requests (==2.25.1)", "six (==1.15.0)", "snowballstemmer (==2.1.0)", "sphinx (==1.8.5)", "sphinx-rtd-theme (==0.4.3)", "sphinxcontrib-serializinghtml (==1.1.4)", "sphinxcontrib-websupport (==1.2.4)", "urllib3 (==1.26.4)"]
-qa = ["flake8 (==3.8.3)", "mypy (==0.782)"]
-testing = ["Django (<3.1)", "attrs", "colorama", "docopt", "pytest (<7.0.0)"]
+qa = ["flake8 (==5.0.4)", "mypy (==0.971)", "types-setuptools (==67.2.0.1)"]
+testing = ["Django", "attrs", "colorama", "docopt", "pytest (<9.0.0)"]
[[package]]
name = "jinja2"
-version = "3.1.2"
+version = "3.1.4"
description = "A very fast and expressive template engine."
-category = "dev"
optional = false
python-versions = ">=3.7"
files = [
- {file = "Jinja2-3.1.2-py3-none-any.whl", hash = "sha256:6088930bfe239f0e6710546ab9c19c9ef35e29792895fed6e6e31a023a182a61"},
- {file = "Jinja2-3.1.2.tar.gz", hash = "sha256:31351a702a408a9e7595a8fc6150fc3f43bb6bf7e319770cbc0db9df9437e852"},
+ {file = "jinja2-3.1.4-py3-none-any.whl", hash = "sha256:bc5dd2abb727a5319567b7a813e6a2e7318c39f4f487cfe6c89c6f9c7d25197d"},
+ {file = "jinja2-3.1.4.tar.gz", hash = "sha256:4a3aee7acbbe7303aede8e9648d13b8bf88a429282aa6122a993f0ac800cb369"},
]
[package.dependencies]
@@ -516,122 +475,122 @@ i18n = ["Babel (>=2.7)"]
[[package]]
name = "markupsafe"
-version = "2.1.1"
+version = "2.1.5"
description = "Safely add untrusted strings to HTML/XML markup."
-category = "dev"
optional = false
python-versions = ">=3.7"
files = [
- {file = "MarkupSafe-2.1.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:86b1f75c4e7c2ac2ccdaec2b9022845dbb81880ca318bb7a0a01fbf7813e3812"},
- {file = "MarkupSafe-2.1.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:f121a1420d4e173a5d96e47e9a0c0dcff965afdf1626d28de1460815f7c4ee7a"},
- {file = "MarkupSafe-2.1.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a49907dd8420c5685cfa064a1335b6754b74541bbb3706c259c02ed65b644b3e"},
- {file = "MarkupSafe-2.1.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:10c1bfff05d95783da83491be968e8fe789263689c02724e0c691933c52994f5"},
- {file = "MarkupSafe-2.1.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b7bd98b796e2b6553da7225aeb61f447f80a1ca64f41d83612e6139ca5213aa4"},
- {file = "MarkupSafe-2.1.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:b09bf97215625a311f669476f44b8b318b075847b49316d3e28c08e41a7a573f"},
- {file = "MarkupSafe-2.1.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:694deca8d702d5db21ec83983ce0bb4b26a578e71fbdbd4fdcd387daa90e4d5e"},
- {file = "MarkupSafe-2.1.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:efc1913fd2ca4f334418481c7e595c00aad186563bbc1ec76067848c7ca0a933"},
- {file = "MarkupSafe-2.1.1-cp310-cp310-win32.whl", hash = "sha256:4a33dea2b688b3190ee12bd7cfa29d39c9ed176bda40bfa11099a3ce5d3a7ac6"},
- {file = "MarkupSafe-2.1.1-cp310-cp310-win_amd64.whl", hash = "sha256:dda30ba7e87fbbb7eab1ec9f58678558fd9a6b8b853530e176eabd064da81417"},
- {file = "MarkupSafe-2.1.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:671cd1187ed5e62818414afe79ed29da836dde67166a9fac6d435873c44fdd02"},
- {file = "MarkupSafe-2.1.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3799351e2336dc91ea70b034983ee71cf2f9533cdff7c14c90ea126bfd95d65a"},
- {file = "MarkupSafe-2.1.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e72591e9ecd94d7feb70c1cbd7be7b3ebea3f548870aa91e2732960fa4d57a37"},
- {file = "MarkupSafe-2.1.1-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6fbf47b5d3728c6aea2abb0589b5d30459e369baa772e0f37a0320185e87c980"},
- {file = "MarkupSafe-2.1.1-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:d5ee4f386140395a2c818d149221149c54849dfcfcb9f1debfe07a8b8bd63f9a"},
- {file = "MarkupSafe-2.1.1-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:bcb3ed405ed3222f9904899563d6fc492ff75cce56cba05e32eff40e6acbeaa3"},
- {file = "MarkupSafe-2.1.1-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:e1c0b87e09fa55a220f058d1d49d3fb8df88fbfab58558f1198e08c1e1de842a"},
- {file = "MarkupSafe-2.1.1-cp37-cp37m-win32.whl", hash = "sha256:8dc1c72a69aa7e082593c4a203dcf94ddb74bb5c8a731e4e1eb68d031e8498ff"},
- {file = "MarkupSafe-2.1.1-cp37-cp37m-win_amd64.whl", hash = "sha256:97a68e6ada378df82bc9f16b800ab77cbf4b2fada0081794318520138c088e4a"},
- {file = "MarkupSafe-2.1.1-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:e8c843bbcda3a2f1e3c2ab25913c80a3c5376cd00c6e8c4a86a89a28c8dc5452"},
- {file = "MarkupSafe-2.1.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:0212a68688482dc52b2d45013df70d169f542b7394fc744c02a57374a4207003"},
- {file = "MarkupSafe-2.1.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8e576a51ad59e4bfaac456023a78f6b5e6e7651dcd383bcc3e18d06f9b55d6d1"},
- {file = "MarkupSafe-2.1.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4b9fe39a2ccc108a4accc2676e77da025ce383c108593d65cc909add5c3bd601"},
- {file = "MarkupSafe-2.1.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:96e37a3dc86e80bf81758c152fe66dbf60ed5eca3d26305edf01892257049925"},
- {file = "MarkupSafe-2.1.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:6d0072fea50feec76a4c418096652f2c3238eaa014b2f94aeb1d56a66b41403f"},
- {file = "MarkupSafe-2.1.1-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:089cf3dbf0cd6c100f02945abeb18484bd1ee57a079aefd52cffd17fba910b88"},
- {file = "MarkupSafe-2.1.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:6a074d34ee7a5ce3effbc526b7083ec9731bb3cbf921bbe1d3005d4d2bdb3a63"},
- {file = "MarkupSafe-2.1.1-cp38-cp38-win32.whl", hash = "sha256:421be9fbf0ffe9ffd7a378aafebbf6f4602d564d34be190fc19a193232fd12b1"},
- {file = "MarkupSafe-2.1.1-cp38-cp38-win_amd64.whl", hash = "sha256:fc7b548b17d238737688817ab67deebb30e8073c95749d55538ed473130ec0c7"},
- {file = "MarkupSafe-2.1.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:e04e26803c9c3851c931eac40c695602c6295b8d432cbe78609649ad9bd2da8a"},
- {file = "MarkupSafe-2.1.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:b87db4360013327109564f0e591bd2a3b318547bcef31b468a92ee504d07ae4f"},
- {file = "MarkupSafe-2.1.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:99a2a507ed3ac881b975a2976d59f38c19386d128e7a9a18b7df6fff1fd4c1d6"},
- {file = "MarkupSafe-2.1.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:56442863ed2b06d19c37f94d999035e15ee982988920e12a5b4ba29b62ad1f77"},
- {file = "MarkupSafe-2.1.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3ce11ee3f23f79dbd06fb3d63e2f6af7b12db1d46932fe7bd8afa259a5996603"},
- {file = "MarkupSafe-2.1.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:33b74d289bd2f5e527beadcaa3f401e0df0a89927c1559c8566c066fa4248ab7"},
- {file = "MarkupSafe-2.1.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:43093fb83d8343aac0b1baa75516da6092f58f41200907ef92448ecab8825135"},
- {file = "MarkupSafe-2.1.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:8e3dcf21f367459434c18e71b2a9532d96547aef8a871872a5bd69a715c15f96"},
- {file = "MarkupSafe-2.1.1-cp39-cp39-win32.whl", hash = "sha256:d4306c36ca495956b6d568d276ac11fdd9c30a36f1b6eb928070dc5360b22e1c"},
- {file = "MarkupSafe-2.1.1-cp39-cp39-win_amd64.whl", hash = "sha256:46d00d6cfecdde84d40e572d63735ef81423ad31184100411e6e3388d405e247"},
- {file = "MarkupSafe-2.1.1.tar.gz", hash = "sha256:7f91197cc9e48f989d12e4e6fbc46495c446636dfc81b9ccf50bb0ec74b91d4b"},
+ {file = "MarkupSafe-2.1.5-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:a17a92de5231666cfbe003f0e4b9b3a7ae3afb1ec2845aadc2bacc93ff85febc"},
+ {file = "MarkupSafe-2.1.5-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:72b6be590cc35924b02c78ef34b467da4ba07e4e0f0454a2c5907f473fc50ce5"},
+ {file = "MarkupSafe-2.1.5-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e61659ba32cf2cf1481e575d0462554625196a1f2fc06a1c777d3f48e8865d46"},
+ {file = "MarkupSafe-2.1.5-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2174c595a0d73a3080ca3257b40096db99799265e1c27cc5a610743acd86d62f"},
+ {file = "MarkupSafe-2.1.5-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ae2ad8ae6ebee9d2d94b17fb62763125f3f374c25618198f40cbb8b525411900"},
+ {file = "MarkupSafe-2.1.5-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:075202fa5b72c86ad32dc7d0b56024ebdbcf2048c0ba09f1cde31bfdd57bcfff"},
+ {file = "MarkupSafe-2.1.5-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:598e3276b64aff0e7b3451b72e94fa3c238d452e7ddcd893c3ab324717456bad"},
+ {file = "MarkupSafe-2.1.5-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:fce659a462a1be54d2ffcacea5e3ba2d74daa74f30f5f143fe0c58636e355fdd"},
+ {file = "MarkupSafe-2.1.5-cp310-cp310-win32.whl", hash = "sha256:d9fad5155d72433c921b782e58892377c44bd6252b5af2f67f16b194987338a4"},
+ {file = "MarkupSafe-2.1.5-cp310-cp310-win_amd64.whl", hash = "sha256:bf50cd79a75d181c9181df03572cdce0fbb75cc353bc350712073108cba98de5"},
+ {file = "MarkupSafe-2.1.5-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:629ddd2ca402ae6dbedfceeba9c46d5f7b2a61d9749597d4307f943ef198fc1f"},
+ {file = "MarkupSafe-2.1.5-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:5b7b716f97b52c5a14bffdf688f971b2d5ef4029127f1ad7a513973cfd818df2"},
+ {file = "MarkupSafe-2.1.5-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6ec585f69cec0aa07d945b20805be741395e28ac1627333b1c5b0105962ffced"},
+ {file = "MarkupSafe-2.1.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b91c037585eba9095565a3556f611e3cbfaa42ca1e865f7b8015fe5c7336d5a5"},
+ {file = "MarkupSafe-2.1.5-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7502934a33b54030eaf1194c21c692a534196063db72176b0c4028e140f8f32c"},
+ {file = "MarkupSafe-2.1.5-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:0e397ac966fdf721b2c528cf028494e86172b4feba51d65f81ffd65c63798f3f"},
+ {file = "MarkupSafe-2.1.5-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:c061bb86a71b42465156a3ee7bd58c8c2ceacdbeb95d05a99893e08b8467359a"},
+ {file = "MarkupSafe-2.1.5-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:3a57fdd7ce31c7ff06cdfbf31dafa96cc533c21e443d57f5b1ecc6cdc668ec7f"},
+ {file = "MarkupSafe-2.1.5-cp311-cp311-win32.whl", hash = "sha256:397081c1a0bfb5124355710fe79478cdbeb39626492b15d399526ae53422b906"},
+ {file = "MarkupSafe-2.1.5-cp311-cp311-win_amd64.whl", hash = "sha256:2b7c57a4dfc4f16f7142221afe5ba4e093e09e728ca65c51f5620c9aaeb9a617"},
+ {file = "MarkupSafe-2.1.5-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:8dec4936e9c3100156f8a2dc89c4b88d5c435175ff03413b443469c7c8c5f4d1"},
+ {file = "MarkupSafe-2.1.5-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:3c6b973f22eb18a789b1460b4b91bf04ae3f0c4234a0a6aa6b0a92f6f7b951d4"},
+ {file = "MarkupSafe-2.1.5-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ac07bad82163452a6884fe8fa0963fb98c2346ba78d779ec06bd7a6262132aee"},
+ {file = "MarkupSafe-2.1.5-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f5dfb42c4604dddc8e4305050aa6deb084540643ed5804d7455b5df8fe16f5e5"},
+ {file = "MarkupSafe-2.1.5-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ea3d8a3d18833cf4304cd2fc9cbb1efe188ca9b5efef2bdac7adc20594a0e46b"},
+ {file = "MarkupSafe-2.1.5-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:d050b3361367a06d752db6ead6e7edeb0009be66bc3bae0ee9d97fb326badc2a"},
+ {file = "MarkupSafe-2.1.5-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:bec0a414d016ac1a18862a519e54b2fd0fc8bbfd6890376898a6c0891dd82e9f"},
+ {file = "MarkupSafe-2.1.5-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:58c98fee265677f63a4385256a6d7683ab1832f3ddd1e66fe948d5880c21a169"},
+ {file = "MarkupSafe-2.1.5-cp312-cp312-win32.whl", hash = "sha256:8590b4ae07a35970728874632fed7bd57b26b0102df2d2b233b6d9d82f6c62ad"},
+ {file = "MarkupSafe-2.1.5-cp312-cp312-win_amd64.whl", hash = "sha256:823b65d8706e32ad2df51ed89496147a42a2a6e01c13cfb6ffb8b1e92bc910bb"},
+ {file = "MarkupSafe-2.1.5-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:c8b29db45f8fe46ad280a7294f5c3ec36dbac9491f2d1c17345be8e69cc5928f"},
+ {file = "MarkupSafe-2.1.5-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ec6a563cff360b50eed26f13adc43e61bc0c04d94b8be985e6fb24b81f6dcfdf"},
+ {file = "MarkupSafe-2.1.5-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a549b9c31bec33820e885335b451286e2969a2d9e24879f83fe904a5ce59d70a"},
+ {file = "MarkupSafe-2.1.5-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4f11aa001c540f62c6166c7726f71f7573b52c68c31f014c25cc7901deea0b52"},
+ {file = "MarkupSafe-2.1.5-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:7b2e5a267c855eea6b4283940daa6e88a285f5f2a67f2220203786dfa59b37e9"},
+ {file = "MarkupSafe-2.1.5-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:2d2d793e36e230fd32babe143b04cec8a8b3eb8a3122d2aceb4a371e6b09b8df"},
+ {file = "MarkupSafe-2.1.5-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:ce409136744f6521e39fd8e2a24c53fa18ad67aa5bc7c2cf83645cce5b5c4e50"},
+ {file = "MarkupSafe-2.1.5-cp37-cp37m-win32.whl", hash = "sha256:4096e9de5c6fdf43fb4f04c26fb114f61ef0bf2e5604b6ee3019d51b69e8c371"},
+ {file = "MarkupSafe-2.1.5-cp37-cp37m-win_amd64.whl", hash = "sha256:4275d846e41ecefa46e2015117a9f491e57a71ddd59bbead77e904dc02b1bed2"},
+ {file = "MarkupSafe-2.1.5-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:656f7526c69fac7f600bd1f400991cc282b417d17539a1b228617081106feb4a"},
+ {file = "MarkupSafe-2.1.5-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:97cafb1f3cbcd3fd2b6fbfb99ae11cdb14deea0736fc2b0952ee177f2b813a46"},
+ {file = "MarkupSafe-2.1.5-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1f3fbcb7ef1f16e48246f704ab79d79da8a46891e2da03f8783a5b6fa41a9532"},
+ {file = "MarkupSafe-2.1.5-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fa9db3f79de01457b03d4f01b34cf91bc0048eb2c3846ff26f66687c2f6d16ab"},
+ {file = "MarkupSafe-2.1.5-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ffee1f21e5ef0d712f9033568f8344d5da8cc2869dbd08d87c84656e6a2d2f68"},
+ {file = "MarkupSafe-2.1.5-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:5dedb4db619ba5a2787a94d877bc8ffc0566f92a01c0ef214865e54ecc9ee5e0"},
+ {file = "MarkupSafe-2.1.5-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:30b600cf0a7ac9234b2638fbc0fb6158ba5bdcdf46aeb631ead21248b9affbc4"},
+ {file = "MarkupSafe-2.1.5-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:8dd717634f5a044f860435c1d8c16a270ddf0ef8588d4887037c5028b859b0c3"},
+ {file = "MarkupSafe-2.1.5-cp38-cp38-win32.whl", hash = "sha256:daa4ee5a243f0f20d528d939d06670a298dd39b1ad5f8a72a4275124a7819eff"},
+ {file = "MarkupSafe-2.1.5-cp38-cp38-win_amd64.whl", hash = "sha256:619bc166c4f2de5caa5a633b8b7326fbe98e0ccbfacabd87268a2b15ff73a029"},
+ {file = "MarkupSafe-2.1.5-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:7a68b554d356a91cce1236aa7682dc01df0edba8d043fd1ce607c49dd3c1edcf"},
+ {file = "MarkupSafe-2.1.5-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:db0b55e0f3cc0be60c1f19efdde9a637c32740486004f20d1cff53c3c0ece4d2"},
+ {file = "MarkupSafe-2.1.5-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3e53af139f8579a6d5f7b76549125f0d94d7e630761a2111bc431fd820e163b8"},
+ {file = "MarkupSafe-2.1.5-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:17b950fccb810b3293638215058e432159d2b71005c74371d784862b7e4683f3"},
+ {file = "MarkupSafe-2.1.5-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4c31f53cdae6ecfa91a77820e8b151dba54ab528ba65dfd235c80b086d68a465"},
+ {file = "MarkupSafe-2.1.5-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:bff1b4290a66b490a2f4719358c0cdcd9bafb6b8f061e45c7a2460866bf50c2e"},
+ {file = "MarkupSafe-2.1.5-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:bc1667f8b83f48511b94671e0e441401371dfd0f0a795c7daa4a3cd1dde55bea"},
+ {file = "MarkupSafe-2.1.5-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:5049256f536511ee3f7e1b3f87d1d1209d327e818e6ae1365e8653d7e3abb6a6"},
+ {file = "MarkupSafe-2.1.5-cp39-cp39-win32.whl", hash = "sha256:00e046b6dd71aa03a41079792f8473dc494d564611a8f89bbbd7cb93295ebdcf"},
+ {file = "MarkupSafe-2.1.5-cp39-cp39-win_amd64.whl", hash = "sha256:fa173ec60341d6bb97a89f5ea19c85c5643c1e7dedebc22f5181eb73573142c5"},
+ {file = "MarkupSafe-2.1.5.tar.gz", hash = "sha256:d283d37a890ba4c1ae73ffadf8046435c76e7bc2247bbb63c00bd1a709c6544b"},
]
[[package]]
name = "matplotlib-inline"
-version = "0.1.6"
+version = "0.1.7"
description = "Inline Matplotlib backend for Jupyter"
-category = "dev"
optional = false
-python-versions = ">=3.5"
+python-versions = ">=3.8"
files = [
- {file = "matplotlib-inline-0.1.6.tar.gz", hash = "sha256:f887e5f10ba98e8d2b150ddcf4702c1e5f8b3a20005eb0f74bfdbd360ee6f304"},
- {file = "matplotlib_inline-0.1.6-py3-none-any.whl", hash = "sha256:f1f41aab5328aa5aaea9b16d083b128102f8712542f819fe7e6a420ff581b311"},
+ {file = "matplotlib_inline-0.1.7-py3-none-any.whl", hash = "sha256:df192d39a4ff8f21b1895d72e6a13f5fcc5099f00fa84384e0ea28c2cc0653ca"},
+ {file = "matplotlib_inline-0.1.7.tar.gz", hash = "sha256:8423b23ec666be3d16e16b60bdd8ac4e86e840ebd1dd11a30b9f117f2fa0ab90"},
]
[package.dependencies]
traitlets = "*"
-[[package]]
-name = "mccabe"
-version = "0.6.1"
-description = "McCabe checker, plugin for flake8"
-category = "dev"
-optional = false
-python-versions = "*"
-files = [
- {file = "mccabe-0.6.1-py2.py3-none-any.whl", hash = "sha256:ab8a6258860da4b6677da4bd2fe5dc2c659cff31b3ee4f7f5d64e79735b80d42"},
- {file = "mccabe-0.6.1.tar.gz", hash = "sha256:dd8d182285a0fe56bace7f45b5e7d1a6ebcbf524e8f3bd87eb0f125271b8831f"},
-]
-
[[package]]
name = "packaging"
-version = "21.3"
+version = "24.2"
description = "Core utilities for Python packages"
-category = "dev"
optional = false
-python-versions = ">=3.6"
+python-versions = ">=3.8"
files = [
- {file = "packaging-21.3-py3-none-any.whl", hash = "sha256:ef103e05f519cdc783ae24ea4e2e0f508a9c99b2d4969652eed6a2e1ea5bd522"},
- {file = "packaging-21.3.tar.gz", hash = "sha256:dd47c42927d89ab911e606518907cc2d3a1f38bbd026385970643f9c5b8ecfeb"},
+ {file = "packaging-24.2-py3-none-any.whl", hash = "sha256:09abb1bccd265c01f4a3aa3f7a7db064b36514d2cba19a2f694fe6150451a759"},
+ {file = "packaging-24.2.tar.gz", hash = "sha256:c228a6dc5e932d346bc5739379109d49e8853dd8223571c7c5b55260edc0b97f"},
]
-[package.dependencies]
-pyparsing = ">=2.0.2,<3.0.5 || >3.0.5"
-
[[package]]
name = "parso"
-version = "0.8.3"
+version = "0.8.4"
description = "A Python Parser"
-category = "dev"
optional = false
python-versions = ">=3.6"
files = [
- {file = "parso-0.8.3-py2.py3-none-any.whl", hash = "sha256:c001d4636cd3aecdaf33cbb40aebb59b094be2a74c556778ef5576c175e19e75"},
- {file = "parso-0.8.3.tar.gz", hash = "sha256:8c07be290bb59f03588915921e29e8a50002acaf2cdc5fa0e0114f91709fafa0"},
+ {file = "parso-0.8.4-py2.py3-none-any.whl", hash = "sha256:a418670a20291dacd2dddc80c377c5c3791378ee1e8d12bffc35420643d43f18"},
+ {file = "parso-0.8.4.tar.gz", hash = "sha256:eb3a7b58240fb99099a345571deecc0f9540ea5f4dd2fe14c2a99d6b281ab92d"},
]
[package.extras]
-qa = ["flake8 (==3.8.3)", "mypy (==0.782)"]
-testing = ["docopt", "pytest (<6.0.0)"]
+qa = ["flake8 (==5.0.4)", "mypy (==0.971)", "types-setuptools (==67.2.0.1)"]
+testing = ["docopt", "pytest"]
[[package]]
name = "pexpect"
-version = "4.8.0"
+version = "4.9.0"
description = "Pexpect allows easy control of interactive console applications."
-category = "dev"
optional = false
python-versions = "*"
files = [
- {file = "pexpect-4.8.0-py2.py3-none-any.whl", hash = "sha256:0b48a55dcb3c05f3329815901ea4fc1537514d6ba867a152b581d69ae3710937"},
- {file = "pexpect-4.8.0.tar.gz", hash = "sha256:fc65a43959d153d0114afe13997d439c22823a27cefceb5ff35c2178c6784c0c"},
+ {file = "pexpect-4.9.0-py2.py3-none-any.whl", hash = "sha256:7236d1e080e4936be2dc3e326cec0af72acf9212a7e1d060210e70a47e253523"},
+ {file = "pexpect-4.9.0.tar.gz", hash = "sha256:ee7d41123f3c9911050ea2c2dac107568dc43b2d3b0c7557a33212c398ead30f"},
]
[package.dependencies]
@@ -641,7 +600,6 @@ ptyprocess = ">=0.5"
name = "pickleshare"
version = "0.7.5"
description = "Tiny 'shelve'-like database with concurrency support"
-category = "dev"
optional = false
python-versions = "*"
files = [
@@ -651,14 +609,13 @@ files = [
[[package]]
name = "pluggy"
-version = "1.0.0"
+version = "1.5.0"
description = "plugin and hook calling mechanisms for python"
-category = "dev"
optional = false
-python-versions = ">=3.6"
+python-versions = ">=3.8"
files = [
- {file = "pluggy-1.0.0-py2.py3-none-any.whl", hash = "sha256:74134bbf457f031a36d68416e1509f34bd5ccc019f0bcc952c7b909d06b37bd3"},
- {file = "pluggy-1.0.0.tar.gz", hash = "sha256:4224373bacce55f955a878bf9cfa763c1e360858e330072059e10bad68531159"},
+ {file = "pluggy-1.5.0-py3-none-any.whl", hash = "sha256:44e1ad92c8ca002de6377e165f3e0f1be63266ab4d554740532335b9d75ea669"},
+ {file = "pluggy-1.5.0.tar.gz", hash = "sha256:2cffa88e94fdc978c4c574f15f9e59b7f4201d439195c3715ca9e2486f1d0cf1"},
]
[package.extras]
@@ -667,14 +624,13 @@ testing = ["pytest", "pytest-benchmark"]
[[package]]
name = "prompt-toolkit"
-version = "3.0.36"
+version = "3.0.48"
description = "Library for building powerful interactive command lines in Python"
-category = "main"
optional = false
-python-versions = ">=3.6.2"
+python-versions = ">=3.7.0"
files = [
- {file = "prompt_toolkit-3.0.36-py3-none-any.whl", hash = "sha256:aa64ad242a462c5ff0363a7b9cfe696c20d55d9fc60c11fd8e632d064804d305"},
- {file = "prompt_toolkit-3.0.36.tar.gz", hash = "sha256:3e163f254bef5a03b146397d7c1963bd3e2812f0964bb9a24e6ec761fd28db63"},
+ {file = "prompt_toolkit-3.0.48-py3-none-any.whl", hash = "sha256:f49a827f90062e411f1ce1f854f2aedb3c23353244f8108b89283587397ac10e"},
+ {file = "prompt_toolkit-3.0.48.tar.gz", hash = "sha256:d6623ab0477a80df74e646bdbc93621143f5caf104206aa29294d53de1a03d90"},
]
[package.dependencies]
@@ -684,7 +640,6 @@ wcwidth = "*"
name = "ptyprocess"
version = "0.7.0"
description = "Run a subprocess in a pseudo terminal"
-category = "dev"
optional = false
python-versions = "*"
files = [
@@ -694,87 +649,44 @@ files = [
[[package]]
name = "pure-eval"
-version = "0.2.2"
+version = "0.2.3"
description = "Safely evaluate AST nodes without side effects"
-category = "dev"
optional = false
python-versions = "*"
files = [
- {file = "pure_eval-0.2.2-py3-none-any.whl", hash = "sha256:01eaab343580944bc56080ebe0a674b39ec44a945e6d09ba7db3cb8cec289350"},
- {file = "pure_eval-0.2.2.tar.gz", hash = "sha256:2b45320af6dfaa1750f543d714b6d1c520a1688dec6fd24d339063ce0aaa9ac3"},
+ {file = "pure_eval-0.2.3-py3-none-any.whl", hash = "sha256:1db8e35b67b3d218d818ae653e27f06c3aa420901fa7b081ca98cbedc874e0d0"},
+ {file = "pure_eval-0.2.3.tar.gz", hash = "sha256:5f4e983f40564c576c7c8635ae88db5956bb2229d7e9237d03b3c0b0190eaf42"},
]
[package.extras]
tests = ["pytest"]
-[[package]]
-name = "pycodestyle"
-version = "2.7.0"
-description = "Python style guide checker"
-category = "dev"
-optional = false
-python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
-files = [
- {file = "pycodestyle-2.7.0-py2.py3-none-any.whl", hash = "sha256:514f76d918fcc0b55c6680472f0a37970994e07bbb80725808c17089be302068"},
- {file = "pycodestyle-2.7.0.tar.gz", hash = "sha256:c389c1d06bf7904078ca03399a4816f974a1d590090fecea0c63ec26ebaf1cef"},
-]
-
-[[package]]
-name = "pyflakes"
-version = "2.3.1"
-description = "passive checker of Python programs"
-category = "dev"
-optional = false
-python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
-files = [
- {file = "pyflakes-2.3.1-py2.py3-none-any.whl", hash = "sha256:7893783d01b8a89811dd72d7dfd4d84ff098e5eed95cfa8905b22bbffe52efc3"},
- {file = "pyflakes-2.3.1.tar.gz", hash = "sha256:f5bc8ecabc05bb9d291eb5203d6810b49040f6ff446a756326104746cc00c1db"},
-]
-
[[package]]
name = "pygments"
-version = "2.13.0"
+version = "2.18.0"
description = "Pygments is a syntax highlighting package written in Python."
-category = "dev"
-optional = false
-python-versions = ">=3.6"
-files = [
- {file = "Pygments-2.13.0-py3-none-any.whl", hash = "sha256:f643f331ab57ba3c9d89212ee4a2dabc6e94f117cf4eefde99a0574720d14c42"},
- {file = "Pygments-2.13.0.tar.gz", hash = "sha256:56a8508ae95f98e2b9bdf93a6be5ae3f7d8af858b43e02c5a2ff083726be40c1"},
-]
-
-[package.extras]
-plugins = ["importlib-metadata"]
-
-[[package]]
-name = "pyparsing"
-version = "3.0.9"
-description = "pyparsing module - Classes and methods to define and execute parsing grammars"
-category = "dev"
optional = false
-python-versions = ">=3.6.8"
+python-versions = ">=3.8"
files = [
- {file = "pyparsing-3.0.9-py3-none-any.whl", hash = "sha256:5026bae9a10eeaefb61dab2f09052b9f4307d44aee4eda64b309723d8d206bbc"},
- {file = "pyparsing-3.0.9.tar.gz", hash = "sha256:2b020ecf7d21b687f219b71ecad3631f644a47f01403fa1d1036b0c6416d70fb"},
+ {file = "pygments-2.18.0-py3-none-any.whl", hash = "sha256:b8e6aca0523f3ab76fee51799c488e38782ac06eafcf95e7ba832985c8e7b13a"},
+ {file = "pygments-2.18.0.tar.gz", hash = "sha256:786ff802f32e91311bff3889f6e9a86e81505fe99f2735bb6d60ae0c5004f199"},
]
[package.extras]
-diagrams = ["jinja2", "railroad-diagrams"]
+windows-terminal = ["colorama (>=0.4.6)"]
[[package]]
name = "pytest"
-version = "7.2.0"
+version = "7.4.4"
description = "pytest: simple powerful testing with Python"
-category = "dev"
optional = false
python-versions = ">=3.7"
files = [
- {file = "pytest-7.2.0-py3-none-any.whl", hash = "sha256:892f933d339f068883b6fd5a459f03d85bfcb355e4981e146d2c7616c21fef71"},
- {file = "pytest-7.2.0.tar.gz", hash = "sha256:c4014eb40e10f11f355ad4e3c2fb2c6c6d1919c73f3b5a433de4708202cade59"},
+ {file = "pytest-7.4.4-py3-none-any.whl", hash = "sha256:b090cdf5ed60bf4c45261be03239c2c1c22df034fbffe691abe93cd80cea01d8"},
+ {file = "pytest-7.4.4.tar.gz", hash = "sha256:2cf0005922c6ace4a3e2ec8b4080eb0d9753fdc93107415332f50ce9e7994280"},
]
[package.dependencies]
-attrs = ">=19.2.0"
colorama = {version = "*", markers = "sys_platform == \"win32\""}
exceptiongroup = {version = ">=1.0.0rc8", markers = "python_version < \"3.11\""}
iniconfig = "*"
@@ -783,18 +695,17 @@ pluggy = ">=0.12,<2.0"
tomli = {version = ">=1.0.0", markers = "python_version < \"3.11\""}
[package.extras]
-testing = ["argcomplete", "hypothesis (>=3.56)", "mock", "nose", "pygments (>=2.7.2)", "requests", "xmlschema"]
+testing = ["argcomplete", "attrs (>=19.2.0)", "hypothesis (>=3.56)", "mock", "nose", "pygments (>=2.7.2)", "requests", "setuptools", "xmlschema"]
[[package]]
name = "pytest-cov"
-version = "4.0.0"
+version = "4.1.0"
description = "Pytest plugin for measuring coverage."
-category = "dev"
optional = false
-python-versions = ">=3.6"
+python-versions = ">=3.7"
files = [
- {file = "pytest-cov-4.0.0.tar.gz", hash = "sha256:996b79efde6433cdbd0088872dbc5fb3ed7fe1578b68cdbba634f14bb8dd0470"},
- {file = "pytest_cov-4.0.0-py3-none-any.whl", hash = "sha256:2feb1b751d66a8bd934e5edfa2e961d11309dc37b73b0eabe73b5945fee20f6b"},
+ {file = "pytest-cov-4.1.0.tar.gz", hash = "sha256:3904b13dfbfec47f003b8e77fd5b589cd11904a21ddf1ab38a64f204d6a10ef6"},
+ {file = "pytest_cov-4.1.0-py3-none-any.whl", hash = "sha256:6ba70b9e97e69fcc3fb45bfeab2d0a138fb65c4d0d6a41ef33983ad114be8c3a"},
]
[package.dependencies]
@@ -806,39 +717,36 @@ testing = ["fields", "hunter", "process-tests", "pytest-xdist", "six", "virtuale
[[package]]
name = "pytest-mock"
-version = "3.10.0"
+version = "3.14.0"
description = "Thin-wrapper around the mock package for easier use with pytest"
-category = "dev"
optional = false
-python-versions = ">=3.7"
+python-versions = ">=3.8"
files = [
- {file = "pytest-mock-3.10.0.tar.gz", hash = "sha256:fbbdb085ef7c252a326fd8cdcac0aa3b1333d8811f131bdcc701002e1be7ed4f"},
- {file = "pytest_mock-3.10.0-py3-none-any.whl", hash = "sha256:f4c973eeae0282963eb293eb173ce91b091a79c1334455acfac9ddee8a1c784b"},
+ {file = "pytest-mock-3.14.0.tar.gz", hash = "sha256:2719255a1efeceadbc056d6bf3df3d1c5015530fb40cf347c0f9afac88410bd0"},
+ {file = "pytest_mock-3.14.0-py3-none-any.whl", hash = "sha256:0b72c38033392a5f4621342fe11e9219ac11ec9d375f8e2a0c164539e0d70f6f"},
]
[package.dependencies]
-pytest = ">=5.0"
+pytest = ">=6.2.5"
[package.extras]
dev = ["pre-commit", "pytest-asyncio", "tox"]
[[package]]
name = "pytz"
-version = "2022.6"
+version = "2022.7.1"
description = "World timezone definitions, modern and historical"
-category = "main"
optional = false
python-versions = "*"
files = [
- {file = "pytz-2022.6-py2.py3-none-any.whl", hash = "sha256:222439474e9c98fced559f1709d89e6c9cbf8d79c794ff3eb9f8800064291427"},
- {file = "pytz-2022.6.tar.gz", hash = "sha256:e89512406b793ca39f5971bc999cc538ce125c0e51c27941bef4568b460095e2"},
+ {file = "pytz-2022.7.1-py2.py3-none-any.whl", hash = "sha256:78f4f37d8198e0627c5f1143240bb0206b8691d8d7ac6d78fee88b78733f8c4a"},
+ {file = "pytz-2022.7.1.tar.gz", hash = "sha256:01a0681c4b9684a28304615eba55d1ab31ae00bf68ec157ec3708a8182dbbcd0"},
]
[[package]]
name = "pytz-deprecation-shim"
version = "0.1.0.post0"
description = "Shims to make deprecation of pytz easier"
-category = "main"
optional = false
python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,>=2.7"
files = [
@@ -852,110 +760,148 @@ tzdata = {version = "*", markers = "python_version >= \"3.6\""}
[[package]]
name = "pyyaml"
-version = "6.0"
+version = "6.0.2"
description = "YAML parser and emitter for Python"
-category = "main"
optional = true
-python-versions = ">=3.6"
+python-versions = ">=3.8"
files = [
- {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-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:d4b0ba9512519522b118090257be113b9468d804b19d63c71dbcf4a48fa32358"},
- {file = "PyYAML-6.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:81957921f441d50af23654aa6c5e5eaf9b06aba7f0a19c18a538dc7ef291c5a1"},
- {file = "PyYAML-6.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:afa17f5bc4d1b10afd4466fd3a44dc0e245382deca5b3c353d8b757f9e3ecb8d"},
- {file = "PyYAML-6.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:dbad0e9d368bb989f4515da330b88a057617d16b6a8245084f1b05400f24609f"},
- {file = "PyYAML-6.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:432557aa2c09802be39460360ddffd48156e30721f5e8d917f01d31694216782"},
- {file = "PyYAML-6.0-cp311-cp311-win32.whl", hash = "sha256:bfaef573a63ba8923503d27530362590ff4f576c626d86a9fed95822a8255fd7"},
- {file = "PyYAML-6.0-cp311-cp311-win_amd64.whl", hash = "sha256:01b45c0191e6d66c470b6cf1b9531a771a83c1c4208272ead47a3ae4f2f603bf"},
- {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"},
+ {file = "PyYAML-6.0.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:0a9a2848a5b7feac301353437eb7d5957887edbf81d56e903999a75a3d743086"},
+ {file = "PyYAML-6.0.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:29717114e51c84ddfba879543fb232a6ed60086602313ca38cce623c1d62cfbf"},
+ {file = "PyYAML-6.0.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8824b5a04a04a047e72eea5cec3bc266db09e35de6bdfe34c9436ac5ee27d237"},
+ {file = "PyYAML-6.0.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7c36280e6fb8385e520936c3cb3b8042851904eba0e58d277dca80a5cfed590b"},
+ {file = "PyYAML-6.0.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ec031d5d2feb36d1d1a24380e4db6d43695f3748343d99434e6f5f9156aaa2ed"},
+ {file = "PyYAML-6.0.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:936d68689298c36b53b29f23c6dbb74de12b4ac12ca6cfe0e047bedceea56180"},
+ {file = "PyYAML-6.0.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:23502f431948090f597378482b4812b0caae32c22213aecf3b55325e049a6c68"},
+ {file = "PyYAML-6.0.2-cp310-cp310-win32.whl", hash = "sha256:2e99c6826ffa974fe6e27cdb5ed0021786b03fc98e5ee3c5bfe1fd5015f42b99"},
+ {file = "PyYAML-6.0.2-cp310-cp310-win_amd64.whl", hash = "sha256:a4d3091415f010369ae4ed1fc6b79def9416358877534caf6a0fdd2146c87a3e"},
+ {file = "PyYAML-6.0.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:cc1c1159b3d456576af7a3e4d1ba7e6924cb39de8f67111c735f6fc832082774"},
+ {file = "PyYAML-6.0.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:1e2120ef853f59c7419231f3bf4e7021f1b936f6ebd222406c3b60212205d2ee"},
+ {file = "PyYAML-6.0.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5d225db5a45f21e78dd9358e58a98702a0302f2659a3c6cd320564b75b86f47c"},
+ {file = "PyYAML-6.0.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5ac9328ec4831237bec75defaf839f7d4564be1e6b25ac710bd1a96321cc8317"},
+ {file = "PyYAML-6.0.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3ad2a3decf9aaba3d29c8f537ac4b243e36bef957511b4766cb0057d32b0be85"},
+ {file = "PyYAML-6.0.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:ff3824dc5261f50c9b0dfb3be22b4567a6f938ccce4587b38952d85fd9e9afe4"},
+ {file = "PyYAML-6.0.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:797b4f722ffa07cc8d62053e4cff1486fa6dc094105d13fea7b1de7d8bf71c9e"},
+ {file = "PyYAML-6.0.2-cp311-cp311-win32.whl", hash = "sha256:11d8f3dd2b9c1207dcaf2ee0bbbfd5991f571186ec9cc78427ba5bd32afae4b5"},
+ {file = "PyYAML-6.0.2-cp311-cp311-win_amd64.whl", hash = "sha256:e10ce637b18caea04431ce14fabcf5c64a1c61ec9c56b071a4b7ca131ca52d44"},
+ {file = "PyYAML-6.0.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:c70c95198c015b85feafc136515252a261a84561b7b1d51e3384e0655ddf25ab"},
+ {file = "PyYAML-6.0.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ce826d6ef20b1bc864f0a68340c8b3287705cae2f8b4b1d932177dcc76721725"},
+ {file = "PyYAML-6.0.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1f71ea527786de97d1a0cc0eacd1defc0985dcf6b3f17bb77dcfc8c34bec4dc5"},
+ {file = "PyYAML-6.0.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9b22676e8097e9e22e36d6b7bda33190d0d400f345f23d4065d48f4ca7ae0425"},
+ {file = "PyYAML-6.0.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:80bab7bfc629882493af4aa31a4cfa43a4c57c83813253626916b8c7ada83476"},
+ {file = "PyYAML-6.0.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:0833f8694549e586547b576dcfaba4a6b55b9e96098b36cdc7ebefe667dfed48"},
+ {file = "PyYAML-6.0.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8b9c7197f7cb2738065c481a0461e50ad02f18c78cd75775628afb4d7137fb3b"},
+ {file = "PyYAML-6.0.2-cp312-cp312-win32.whl", hash = "sha256:ef6107725bd54b262d6dedcc2af448a266975032bc85ef0172c5f059da6325b4"},
+ {file = "PyYAML-6.0.2-cp312-cp312-win_amd64.whl", hash = "sha256:7e7401d0de89a9a855c839bc697c079a4af81cf878373abd7dc625847d25cbd8"},
+ {file = "PyYAML-6.0.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:efdca5630322a10774e8e98e1af481aad470dd62c3170801852d752aa7a783ba"},
+ {file = "PyYAML-6.0.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:50187695423ffe49e2deacb8cd10510bc361faac997de9efef88badc3bb9e2d1"},
+ {file = "PyYAML-6.0.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0ffe8360bab4910ef1b9e87fb812d8bc0a308b0d0eef8c8f44e0254ab3b07133"},
+ {file = "PyYAML-6.0.2-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:17e311b6c678207928d649faa7cb0d7b4c26a0ba73d41e99c4fff6b6c3276484"},
+ {file = "PyYAML-6.0.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:70b189594dbe54f75ab3a1acec5f1e3faa7e8cf2f1e08d9b561cb41b845f69d5"},
+ {file = "PyYAML-6.0.2-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:41e4e3953a79407c794916fa277a82531dd93aad34e29c2a514c2c0c5fe971cc"},
+ {file = "PyYAML-6.0.2-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:68ccc6023a3400877818152ad9a1033e3db8625d899c72eacb5a668902e4d652"},
+ {file = "PyYAML-6.0.2-cp313-cp313-win32.whl", hash = "sha256:bc2fa7c6b47d6bc618dd7fb02ef6fdedb1090ec036abab80d4681424b84c1183"},
+ {file = "PyYAML-6.0.2-cp313-cp313-win_amd64.whl", hash = "sha256:8388ee1976c416731879ac16da0aff3f63b286ffdd57cdeb95f3f2e085687563"},
+ {file = "PyYAML-6.0.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:24471b829b3bf607e04e88d79542a9d48bb037c2267d7927a874e6c205ca7e9a"},
+ {file = "PyYAML-6.0.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d7fded462629cfa4b685c5416b949ebad6cec74af5e2d42905d41e257e0869f5"},
+ {file = "PyYAML-6.0.2-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d84a1718ee396f54f3a086ea0a66d8e552b2ab2017ef8b420e92edbc841c352d"},
+ {file = "PyYAML-6.0.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9056c1ecd25795207ad294bcf39f2db3d845767be0ea6e6a34d856f006006083"},
+ {file = "PyYAML-6.0.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:82d09873e40955485746739bcb8b4586983670466c23382c19cffecbf1fd8706"},
+ {file = "PyYAML-6.0.2-cp38-cp38-win32.whl", hash = "sha256:43fa96a3ca0d6b1812e01ced1044a003533c47f6ee8aca31724f78e93ccc089a"},
+ {file = "PyYAML-6.0.2-cp38-cp38-win_amd64.whl", hash = "sha256:01179a4a8559ab5de078078f37e5c1a30d76bb88519906844fd7bdea1b7729ff"},
+ {file = "PyYAML-6.0.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:688ba32a1cffef67fd2e9398a2efebaea461578b0923624778664cc1c914db5d"},
+ {file = "PyYAML-6.0.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:a8786accb172bd8afb8be14490a16625cbc387036876ab6ba70912730faf8e1f"},
+ {file = "PyYAML-6.0.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d8e03406cac8513435335dbab54c0d385e4a49e4945d2909a581c83647ca0290"},
+ {file = "PyYAML-6.0.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f753120cb8181e736c57ef7636e83f31b9c0d1722c516f7e86cf15b7aa57ff12"},
+ {file = "PyYAML-6.0.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3b1fdb9dc17f5a7677423d508ab4f243a726dea51fa5e70992e59a7411c89d19"},
+ {file = "PyYAML-6.0.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:0b69e4ce7a131fe56b7e4d770c67429700908fc0752af059838b1cfb41960e4e"},
+ {file = "PyYAML-6.0.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:a9f8c2e67970f13b16084e04f134610fd1d374bf477b17ec1599185cf611d725"},
+ {file = "PyYAML-6.0.2-cp39-cp39-win32.whl", hash = "sha256:6395c297d42274772abc367baaa79683958044e5d3835486c16da75d2a694631"},
+ {file = "PyYAML-6.0.2-cp39-cp39-win_amd64.whl", hash = "sha256:39693e1f8320ae4f43943590b49779ffb98acb81f788220ea932a6b6c51004d8"},
+ {file = "pyyaml-6.0.2.tar.gz", hash = "sha256:d584d9ec91ad65861cc08d42e834324ef890a082e591037abe114850ff7bbc3e"},
]
[[package]]
name = "requests"
-version = "2.28.1"
+version = "2.32.3"
description = "Python HTTP for Humans."
-category = "dev"
optional = false
-python-versions = ">=3.7, <4"
+python-versions = ">=3.8"
files = [
- {file = "requests-2.28.1-py3-none-any.whl", hash = "sha256:8fefa2a1a1365bf5520aac41836fbee479da67864514bdb821f31ce07ce65349"},
- {file = "requests-2.28.1.tar.gz", hash = "sha256:7c5599b102feddaa661c826c56ab4fee28bfd17f5abca1ebbe3e7f19d7c97983"},
+ {file = "requests-2.32.3-py3-none-any.whl", hash = "sha256:70761cfe03c773ceb22aa2f671b4757976145175cdfca038c02654d061d6dcc6"},
+ {file = "requests-2.32.3.tar.gz", hash = "sha256:55365417734eb18255590a9ff9eb97e9e1da868d4ccd6402399eaf68af20a760"},
]
[package.dependencies]
certifi = ">=2017.4.17"
-charset-normalizer = ">=2,<3"
+charset-normalizer = ">=2,<4"
idna = ">=2.5,<4"
-urllib3 = ">=1.21.1,<1.27"
+urllib3 = ">=1.21.1,<3"
[package.extras]
socks = ["PySocks (>=1.5.6,!=1.5.7)"]
use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"]
+[[package]]
+name = "ruff"
+version = "0.3.7"
+description = "An extremely fast Python linter and code formatter, written in Rust."
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "ruff-0.3.7-py3-none-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:0e8377cccb2f07abd25e84fc5b2cbe48eeb0fea9f1719cad7caedb061d70e5ce"},
+ {file = "ruff-0.3.7-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:15a4d1cc1e64e556fa0d67bfd388fed416b7f3b26d5d1c3e7d192c897e39ba4b"},
+ {file = "ruff-0.3.7-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d28bdf3d7dc71dd46929fafeec98ba89b7c3550c3f0978e36389b5631b793663"},
+ {file = "ruff-0.3.7-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:379b67d4f49774ba679593b232dcd90d9e10f04d96e3c8ce4a28037ae473f7bb"},
+ {file = "ruff-0.3.7-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c060aea8ad5ef21cdfbbe05475ab5104ce7827b639a78dd55383a6e9895b7c51"},
+ {file = "ruff-0.3.7-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:ebf8f615dde968272d70502c083ebf963b6781aacd3079081e03b32adfe4d58a"},
+ {file = "ruff-0.3.7-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d48098bd8f5c38897b03604f5428901b65e3c97d40b3952e38637b5404b739a2"},
+ {file = "ruff-0.3.7-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:da8a4fda219bf9024692b1bc68c9cff4b80507879ada8769dc7e985755d662ea"},
+ {file = "ruff-0.3.7-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6c44e0149f1d8b48c4d5c33d88c677a4aa22fd09b1683d6a7ff55b816b5d074f"},
+ {file = "ruff-0.3.7-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:3050ec0af72b709a62ecc2aca941b9cd479a7bf2b36cc4562f0033d688e44fa1"},
+ {file = "ruff-0.3.7-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:a29cc38e4c1ab00da18a3f6777f8b50099d73326981bb7d182e54a9a21bb4ff7"},
+ {file = "ruff-0.3.7-py3-none-musllinux_1_2_i686.whl", hash = "sha256:5b15cc59c19edca917f51b1956637db47e200b0fc5e6e1878233d3a938384b0b"},
+ {file = "ruff-0.3.7-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:e491045781b1e38b72c91247cf4634f040f8d0cb3e6d3d64d38dcf43616650b4"},
+ {file = "ruff-0.3.7-py3-none-win32.whl", hash = "sha256:bc931de87593d64fad3a22e201e55ad76271f1d5bfc44e1a1887edd0903c7d9f"},
+ {file = "ruff-0.3.7-py3-none-win_amd64.whl", hash = "sha256:5ef0e501e1e39f35e03c2acb1d1238c595b8bb36cf7a170e7c1df1b73da00e74"},
+ {file = "ruff-0.3.7-py3-none-win_arm64.whl", hash = "sha256:789e144f6dc7019d1f92a812891c645274ed08af6037d11fc65fcbc183b7d59f"},
+ {file = "ruff-0.3.7.tar.gz", hash = "sha256:d5c1aebee5162c2226784800ae031f660c350e7a3402c4d1f8ea4e97e232e3ba"},
+]
+
[[package]]
name = "setuptools"
-version = "65.6.3"
+version = "75.3.0"
description = "Easily download, build, install, upgrade, and uninstall Python packages"
-category = "dev"
optional = false
-python-versions = ">=3.7"
+python-versions = ">=3.8"
files = [
- {file = "setuptools-65.6.3-py3-none-any.whl", hash = "sha256:57f6f22bde4e042978bcd50176fdb381d7c21a9efa4041202288d3737a0c6a54"},
- {file = "setuptools-65.6.3.tar.gz", hash = "sha256:a7620757bf984b58deaf32fc8a4577a9bbc0850cf92c20e1ce41c38c19e5fb75"},
+ {file = "setuptools-75.3.0-py3-none-any.whl", hash = "sha256:f2504966861356aa38616760c0f66568e535562374995367b4e69c7143cf6bcd"},
+ {file = "setuptools-75.3.0.tar.gz", hash = "sha256:fba5dd4d766e97be1b1681d98712680ae8f2f26d7881245f2ce9e40714f1a686"},
]
[package.extras]
-docs = ["furo", "jaraco.packaging (>=9)", "jaraco.tidelift (>=1.4)", "pygments-github-lexers (==0.0.5)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-favicon", "sphinx-hoverxref (<2)", "sphinx-inline-tabs", "sphinx-notfound-page (==0.8.3)", "sphinx-reredirects", "sphinxcontrib-towncrier"]
-testing = ["build[virtualenv]", "filelock (>=3.4.0)", "flake8 (<5)", "flake8-2020", "ini2toml[lite] (>=0.9)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "pip (>=19.1)", "pip-run (>=8.8)", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=1.3)", "pytest-flake8", "pytest-mypy (>=0.9.1)", "pytest-perf", "pytest-timeout", "pytest-xdist", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel"]
-testing-integration = ["build[virtualenv]", "filelock (>=3.4.0)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "pytest", "pytest-enabler", "pytest-xdist", "tomli", "virtualenv (>=13.0.0)", "wheel"]
+check = ["pytest-checkdocs (>=2.4)", "pytest-ruff (>=0.2.1)", "ruff (>=0.5.2)"]
+core = ["importlib-metadata (>=6)", "importlib-resources (>=5.10.2)", "jaraco.collections", "jaraco.functools", "jaraco.text (>=3.7)", "more-itertools", "more-itertools (>=8.8)", "packaging", "packaging (>=24)", "platformdirs (>=4.2.2)", "tomli (>=2.0.1)", "wheel (>=0.43.0)"]
+cover = ["pytest-cov"]
+doc = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "pygments-github-lexers (==0.0.5)", "pyproject-hooks (!=1.1)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-favicon", "sphinx-inline-tabs", "sphinx-lint", "sphinx-notfound-page (>=1,<2)", "sphinx-reredirects", "sphinxcontrib-towncrier", "towncrier (<24.7)"]
+enabler = ["pytest-enabler (>=2.2)"]
+test = ["build[virtualenv] (>=1.0.3)", "filelock (>=3.4.0)", "ini2toml[lite] (>=0.14)", "jaraco.develop (>=7.21)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "jaraco.test (>=5.5)", "packaging (>=23.2)", "pip (>=19.1)", "pyproject-hooks (!=1.1)", "pytest (>=6,!=8.1.*)", "pytest-home (>=0.5)", "pytest-perf", "pytest-subprocess", "pytest-timeout", "pytest-xdist (>=3)", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel (>=0.44.0)"]
+type = ["importlib-metadata (>=7.0.2)", "jaraco.develop (>=7.21)", "mypy (==1.12.*)", "pytest-mypy"]
[[package]]
name = "six"
-version = "1.16.0"
+version = "1.17.0"
description = "Python 2 and 3 compatibility utilities"
-category = "main"
optional = false
-python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*"
+python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7"
files = [
- {file = "six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"},
- {file = "six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926"},
+ {file = "six-1.17.0-py2.py3-none-any.whl", hash = "sha256:4721f391ed90541fddacab5acf947aa0d3dc7d27b2e1e8eda2be8970586c3274"},
+ {file = "six-1.17.0.tar.gz", hash = "sha256:ff70335d468e7eb6ec65b95b99d3a2836546063f63acc5171de367e834932a81"},
]
[[package]]
name = "snowballstemmer"
version = "2.2.0"
description = "This package provides 29 stemmers for 28 languages generated from Snowball algorithms."
-category = "dev"
optional = false
python-versions = "*"
files = [
@@ -965,21 +911,20 @@ files = [
[[package]]
name = "sphinx"
-version = "1.8.6"
+version = "1.8.5"
description = "Python documentation generator"
-category = "dev"
optional = false
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
files = [
- {file = "Sphinx-1.8.6-py2.py3-none-any.whl", hash = "sha256:5973adbb19a5de30e15ab394ec8bc05700317fa83f122c349dd01804d983720f"},
- {file = "Sphinx-1.8.6.tar.gz", hash = "sha256:e096b1b369dbb0fcb95a31ba8c9e1ae98c588e601f08eada032248e1696de4b1"},
+ {file = "Sphinx-1.8.5-py2.py3-none-any.whl", hash = "sha256:9f3e17c64b34afc653d7c5ec95766e03043cc6d80b0de224f59b6b6e19d37c3c"},
+ {file = "Sphinx-1.8.5.tar.gz", hash = "sha256:c7658aab75c920288a8cf6f09f244c6cfdae30d82d803ac1634d9f223a80ca08"},
]
[package.dependencies]
alabaster = ">=0.7,<0.8"
babel = ">=1.3,<2.0 || >2.0"
colorama = {version = ">=0.3.5", markers = "sys_platform == \"win32\""}
-docutils = ">=0.11,<0.18"
+docutils = ">=0.11"
imagesize = "*"
Jinja2 = ">=2.3"
packaging = "*"
@@ -996,28 +941,41 @@ websupport = ["sqlalchemy (>=0.9)", "whoosh (>=2.0)"]
[[package]]
name = "sphinx-rtd-theme"
-version = "1.1.1"
+version = "1.3.0"
description = "Read the Docs theme for Sphinx"
-category = "dev"
optional = false
-python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,>=2.7"
+python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,>=2.7"
files = [
- {file = "sphinx_rtd_theme-1.1.1-py2.py3-none-any.whl", hash = "sha256:31faa07d3e97c8955637fc3f1423a5ab2c44b74b8cc558a51498c202ce5cbda7"},
- {file = "sphinx_rtd_theme-1.1.1.tar.gz", hash = "sha256:6146c845f1e1947b3c3dd4432c28998a1693ccc742b4f9ad7c63129f0757c103"},
+ {file = "sphinx_rtd_theme-1.3.0-py2.py3-none-any.whl", hash = "sha256:46ddef89cc2416a81ecfbeaceab1881948c014b1b6e4450b815311a89fb977b0"},
+ {file = "sphinx_rtd_theme-1.3.0.tar.gz", hash = "sha256:590b030c7abb9cf038ec053b95e5380b5c70d61591eb0b552063fbe7c41f0931"},
]
[package.dependencies]
-docutils = "<0.18"
-sphinx = ">=1.6,<6"
+docutils = "<0.19"
+sphinx = ">=1.6,<8"
+sphinxcontrib-jquery = ">=4,<5"
[package.extras]
dev = ["bump2version", "sphinxcontrib-httpdomain", "transifex-client", "wheel"]
+[[package]]
+name = "sphinxcontrib-jquery"
+version = "4.1"
+description = "Extension to include jQuery on newer Sphinx releases"
+optional = false
+python-versions = ">=2.7"
+files = [
+ {file = "sphinxcontrib-jquery-4.1.tar.gz", hash = "sha256:1620739f04e36a2c779f1a131a2dfd49b2fd07351bf1968ced074365933abc7a"},
+ {file = "sphinxcontrib_jquery-4.1-py2.py3-none-any.whl", hash = "sha256:f936030d7d0147dd026a4f2b5a57343d233f1fc7b363f68b3d4f1cb0993878ae"},
+]
+
+[package.dependencies]
+Sphinx = ">=1.8"
+
[[package]]
name = "sphinxcontrib-serializinghtml"
version = "1.1.5"
description = "sphinxcontrib-serializinghtml is a sphinx extension which outputs \"serialized\" HTML files (json and pickle)."
-category = "dev"
optional = false
python-versions = ">=3.5"
files = [
@@ -1033,7 +991,6 @@ test = ["pytest"]
name = "sphinxcontrib-websupport"
version = "1.2.4"
description = "Sphinx API for Web Apps"
-category = "dev"
optional = false
python-versions = ">=3.5"
files = [
@@ -1050,14 +1007,13 @@ test = ["Sphinx", "pytest", "sqlalchemy", "whoosh"]
[[package]]
name = "stack-data"
-version = "0.6.2"
+version = "0.6.3"
description = "Extract data from python stack frames and tracebacks for informative displays"
-category = "dev"
optional = false
python-versions = "*"
files = [
- {file = "stack_data-0.6.2-py3-none-any.whl", hash = "sha256:cbb2a53eb64e5785878201a97ed7c7b94883f48b87bfb0bbe8b623c74679e4a8"},
- {file = "stack_data-0.6.2.tar.gz", hash = "sha256:32d2dd0376772d01b6cb9fc996f3c8b57a357089dec328ed4b6553d037eaf815"},
+ {file = "stack_data-0.6.3-py3-none-any.whl", hash = "sha256:d5558e0c25a4cb0853cddad3d77da9891a08cb85dd9f9f91b9f8cd66e511e695"},
+ {file = "stack_data-0.6.3.tar.gz", hash = "sha256:836a778de4fec4dcd1dcd89ed8abff8a221f58308462e1c4aa2a3cf30148f0b9"},
]
[package.dependencies]
@@ -1070,54 +1026,91 @@ tests = ["cython", "littleutils", "pygments", "pytest", "typeguard"]
[[package]]
name = "tomli"
-version = "2.0.1"
+version = "2.2.1"
description = "A lil' TOML parser"
-category = "dev"
optional = false
-python-versions = ">=3.7"
+python-versions = ">=3.8"
files = [
- {file = "tomli-2.0.1-py3-none-any.whl", hash = "sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc"},
- {file = "tomli-2.0.1.tar.gz", hash = "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f"},
+ {file = "tomli-2.2.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:678e4fa69e4575eb77d103de3df8a895e1591b48e740211bd1067378c69e8249"},
+ {file = "tomli-2.2.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:023aa114dd824ade0100497eb2318602af309e5a55595f76b626d6d9f3b7b0a6"},
+ {file = "tomli-2.2.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ece47d672db52ac607a3d9599a9d48dcb2f2f735c6c2d1f34130085bb12b112a"},
+ {file = "tomli-2.2.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6972ca9c9cc9f0acaa56a8ca1ff51e7af152a9f87fb64623e31d5c83700080ee"},
+ {file = "tomli-2.2.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c954d2250168d28797dd4e3ac5cf812a406cd5a92674ee4c8f123c889786aa8e"},
+ {file = "tomli-2.2.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:8dd28b3e155b80f4d54beb40a441d366adcfe740969820caf156c019fb5c7ec4"},
+ {file = "tomli-2.2.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:e59e304978767a54663af13c07b3d1af22ddee3bb2fb0618ca1593e4f593a106"},
+ {file = "tomli-2.2.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:33580bccab0338d00994d7f16f4c4ec25b776af3ffaac1ed74e0b3fc95e885a8"},
+ {file = "tomli-2.2.1-cp311-cp311-win32.whl", hash = "sha256:465af0e0875402f1d226519c9904f37254b3045fc5084697cefb9bdde1ff99ff"},
+ {file = "tomli-2.2.1-cp311-cp311-win_amd64.whl", hash = "sha256:2d0f2fdd22b02c6d81637a3c95f8cd77f995846af7414c5c4b8d0545afa1bc4b"},
+ {file = "tomli-2.2.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:4a8f6e44de52d5e6c657c9fe83b562f5f4256d8ebbfe4ff922c495620a7f6cea"},
+ {file = "tomli-2.2.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:8d57ca8095a641b8237d5b079147646153d22552f1c637fd3ba7f4b0b29167a8"},
+ {file = "tomli-2.2.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4e340144ad7ae1533cb897d406382b4b6fede8890a03738ff1683af800d54192"},
+ {file = "tomli-2.2.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:db2b95f9de79181805df90bedc5a5ab4c165e6ec3fe99f970d0e302f384ad222"},
+ {file = "tomli-2.2.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:40741994320b232529c802f8bc86da4e1aa9f413db394617b9a256ae0f9a7f77"},
+ {file = "tomli-2.2.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:400e720fe168c0f8521520190686ef8ef033fb19fc493da09779e592861b78c6"},
+ {file = "tomli-2.2.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:02abe224de6ae62c19f090f68da4e27b10af2b93213d36cf44e6e1c5abd19fdd"},
+ {file = "tomli-2.2.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:b82ebccc8c8a36f2094e969560a1b836758481f3dc360ce9a3277c65f374285e"},
+ {file = "tomli-2.2.1-cp312-cp312-win32.whl", hash = "sha256:889f80ef92701b9dbb224e49ec87c645ce5df3fa2cc548664eb8a25e03127a98"},
+ {file = "tomli-2.2.1-cp312-cp312-win_amd64.whl", hash = "sha256:7fc04e92e1d624a4a63c76474610238576942d6b8950a2d7f908a340494e67e4"},
+ {file = "tomli-2.2.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:f4039b9cbc3048b2416cc57ab3bda989a6fcf9b36cf8937f01a6e731b64f80d7"},
+ {file = "tomli-2.2.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:286f0ca2ffeeb5b9bd4fcc8d6c330534323ec51b2f52da063b11c502da16f30c"},
+ {file = "tomli-2.2.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a92ef1a44547e894e2a17d24e7557a5e85a9e1d0048b0b5e7541f76c5032cb13"},
+ {file = "tomli-2.2.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9316dc65bed1684c9a98ee68759ceaed29d229e985297003e494aa825ebb0281"},
+ {file = "tomli-2.2.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e85e99945e688e32d5a35c1ff38ed0b3f41f43fad8df0bdf79f72b2ba7bc5272"},
+ {file = "tomli-2.2.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:ac065718db92ca818f8d6141b5f66369833d4a80a9d74435a268c52bdfa73140"},
+ {file = "tomli-2.2.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:d920f33822747519673ee656a4b6ac33e382eca9d331c87770faa3eef562aeb2"},
+ {file = "tomli-2.2.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:a198f10c4d1b1375d7687bc25294306e551bf1abfa4eace6650070a5c1ae2744"},
+ {file = "tomli-2.2.1-cp313-cp313-win32.whl", hash = "sha256:d3f5614314d758649ab2ab3a62d4f2004c825922f9e370b29416484086b264ec"},
+ {file = "tomli-2.2.1-cp313-cp313-win_amd64.whl", hash = "sha256:a38aa0308e754b0e3c67e344754dff64999ff9b513e691d0e786265c93583c69"},
+ {file = "tomli-2.2.1-py3-none-any.whl", hash = "sha256:cb55c73c5f4408779d0cf3eef9f762b9c9f147a77de7b258bef0a5628adc85cc"},
+ {file = "tomli-2.2.1.tar.gz", hash = "sha256:cd45e1dc79c835ce60f7404ec8119f2eb06d38b1deba146f07ced3bbc44505ff"},
]
[[package]]
name = "traitlets"
-version = "5.6.0"
+version = "5.14.3"
description = "Traitlets Python configuration system"
-category = "dev"
optional = false
-python-versions = ">=3.7"
+python-versions = ">=3.8"
files = [
- {file = "traitlets-5.6.0-py3-none-any.whl", hash = "sha256:1410755385d778aed847d68deb99b3ba30fbbf489e17a1e8cbb753060d5cce73"},
- {file = "traitlets-5.6.0.tar.gz", hash = "sha256:10b6ed1c9cedee83e795db70a8b9c2db157bb3778ec4587a349ecb7ef3b1033b"},
+ {file = "traitlets-5.14.3-py3-none-any.whl", hash = "sha256:b74e89e397b1ed28cc831db7aea759ba6640cb3de13090ca145426688ff1ac4f"},
+ {file = "traitlets-5.14.3.tar.gz", hash = "sha256:9ed0579d3502c94b4b3732ac120375cda96f923114522847de4b3bb98b96b6b7"},
]
[package.extras]
docs = ["myst-parser", "pydata-sphinx-theme", "sphinx"]
-test = ["pre-commit", "pytest"]
+test = ["argcomplete (>=3.0.3)", "mypy (>=1.7.0)", "pre-commit", "pytest (>=7.0,<8.2)", "pytest-mock", "pytest-mypy-testing"]
+
+[[package]]
+name = "typing-extensions"
+version = "4.12.2"
+description = "Backported and Experimental Type Hints for Python 3.8+"
+optional = false
+python-versions = ">=3.8"
+files = [
+ {file = "typing_extensions-4.12.2-py3-none-any.whl", hash = "sha256:04e5ca0351e0f3f85c6853954072df659d0d13fac324d0072316b67d7794700d"},
+ {file = "typing_extensions-4.12.2.tar.gz", hash = "sha256:1a7ead55c7e559dd4dee8856e3a88b41225abfe1ce8df57b7c13915fe121ffb8"},
+]
[[package]]
name = "tzdata"
-version = "2022.7"
+version = "2024.2"
description = "Provider of IANA time zone data"
-category = "main"
optional = false
python-versions = ">=2"
files = [
- {file = "tzdata-2022.7-py2.py3-none-any.whl", hash = "sha256:2b88858b0e3120792a3c0635c23daf36a7d7eeeca657c323da299d2094402a0d"},
- {file = "tzdata-2022.7.tar.gz", hash = "sha256:fe5f866eddd8b96e9fcba978f8e503c909b19ea7efda11e52e39494bad3a7bfa"},
+ {file = "tzdata-2024.2-py2.py3-none-any.whl", hash = "sha256:a48093786cdcde33cad18c2555e8532f34422074448fbc874186f0abd79565cd"},
+ {file = "tzdata-2024.2.tar.gz", hash = "sha256:7d85cc416e9382e69095b7bdf4afd9e3880418a2413feec7069d533d6b4e31cc"},
]
[[package]]
name = "tzlocal"
-version = "4.2"
+version = "4.3.1"
description = "tzinfo object for the local timezone"
-category = "main"
optional = false
-python-versions = ">=3.6"
+python-versions = ">=3.7"
files = [
- {file = "tzlocal-4.2-py3-none-any.whl", hash = "sha256:89885494684c929d9191c57aa27502afc87a579be5cdd3225c77c463ea043745"},
- {file = "tzlocal-4.2.tar.gz", hash = "sha256:ee5842fa3a795f023514ac2d801c4a81d1743bbe642e3940143326b3a00addd7"},
+ {file = "tzlocal-4.3.1-py3-none-any.whl", hash = "sha256:67d7e7f4ce0a98e9dfde2e02474c60fe846ed032d78b555c554c2e9cba472d84"},
+ {file = "tzlocal-4.3.1.tar.gz", hash = "sha256:ee32ef8c20803c19a96ed366addd3d4a729ef6309cb5c7359a0cc2eeeb7fa46a"},
]
[package.dependencies]
@@ -1126,31 +1119,29 @@ pytz-deprecation-shim = "*"
tzdata = {version = "*", markers = "platform_system == \"Windows\""}
[package.extras]
-devenv = ["black", "pyroma", "pytest-cov", "zest.releaser"]
-test = ["pytest (>=4.3)", "pytest-mock (>=3.3)"]
+devenv = ["black", "check-manifest", "flake8", "pyroma", "pytest (>=4.3)", "pytest-cov", "pytest-mock (>=3.3)", "zest.releaser"]
[[package]]
name = "urllib3"
-version = "1.26.13"
+version = "2.2.3"
description = "HTTP library with thread-safe connection pooling, file post, and more."
-category = "dev"
optional = false
-python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*"
+python-versions = ">=3.8"
files = [
- {file = "urllib3-1.26.13-py2.py3-none-any.whl", hash = "sha256:47cc05d99aaa09c9e72ed5809b60e7ba354e64b59c9c173ac3018642d8bb41fc"},
- {file = "urllib3-1.26.13.tar.gz", hash = "sha256:c083dd0dce68dbfbe1129d5271cb90f9447dea7d52097c6e0126120c521ddea8"},
+ {file = "urllib3-2.2.3-py3-none-any.whl", hash = "sha256:ca899ca043dcb1bafa3e262d73aa25c465bfb49e0bd9dd5d59f1d0acba2f8fac"},
+ {file = "urllib3-2.2.3.tar.gz", hash = "sha256:e7d814a81dad81e6caf2ec9fdedb284ecc9c73076b62654547cc64ccdcae26e9"},
]
[package.extras]
-brotli = ["brotli (>=1.0.9)", "brotlicffi (>=0.8.0)", "brotlipy (>=0.6.0)"]
-secure = ["certifi", "cryptography (>=1.3.4)", "idna (>=2.0.0)", "ipaddress", "pyOpenSSL (>=0.14)", "urllib3-secure-extra"]
-socks = ["PySocks (>=1.5.6,!=1.5.7,<2.0)"]
+brotli = ["brotli (>=1.0.9)", "brotlicffi (>=0.8.0)"]
+h2 = ["h2 (>=4,<5)"]
+socks = ["pysocks (>=1.5.6,!=1.5.7,<2.0)"]
+zstd = ["zstandard (>=0.18.0)"]
[[package]]
name = "validators"
version = "0.18.2"
description = "Python Data Validation for Humans™."
-category = "main"
optional = false
python-versions = ">=3.4"
files = [
@@ -1167,20 +1158,38 @@ test = ["flake8 (>=2.4.0)", "isort (>=4.2.2)", "pytest (>=2.2.3)"]
[[package]]
name = "wcwidth"
-version = "0.2.5"
+version = "0.2.13"
description = "Measures the displayed width of unicode strings in a terminal"
-category = "main"
optional = false
python-versions = "*"
files = [
- {file = "wcwidth-0.2.5-py2.py3-none-any.whl", hash = "sha256:beb4802a9cebb9144e99086eff703a642a13d6a0052920003a230f3294bbe784"},
- {file = "wcwidth-0.2.5.tar.gz", hash = "sha256:c4d647b99872929fdb7bdcaa4fbe7f01413ed3d98077df798530e5b04f116c83"},
+ {file = "wcwidth-0.2.13-py2.py3-none-any.whl", hash = "sha256:3da69048e4540d84af32131829ff948f1e022c1c6bdb8d6102117aac784f6859"},
+ {file = "wcwidth-0.2.13.tar.gz", hash = "sha256:72ea0c06399eb286d978fdedb6923a9eb47e1c486ce63e9b4e64fc18303972b5"},
+]
+
+[[package]]
+name = "zipp"
+version = "3.20.2"
+description = "Backport of pathlib-compatible object wrapper for zip files"
+optional = false
+python-versions = ">=3.8"
+files = [
+ {file = "zipp-3.20.2-py3-none-any.whl", hash = "sha256:a817ac80d6cf4b23bf7f2828b7cabf326f15a001bea8b1f9b49631780ba28350"},
+ {file = "zipp-3.20.2.tar.gz", hash = "sha256:bc9eb26f4506fda01b81bcde0ca78103b6e62f991b381fec825435c836edbc29"},
]
+[package.extras]
+check = ["pytest-checkdocs (>=2.4)", "pytest-ruff (>=0.2.1)"]
+cover = ["pytest-cov"]
+doc = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"]
+enabler = ["pytest-enabler (>=2.2)"]
+test = ["big-O", "importlib-resources", "jaraco.functools", "jaraco.itertools", "jaraco.test", "more-itertools", "pytest (>=6,!=8.1.*)", "pytest-ignore-flaky"]
+type = ["pytest-mypy"]
+
[extras]
yaml = ["PyYAML"]
[metadata]
lock-version = "2.0"
-python-versions = "^3.8"
-content-hash = "4347a35f73b4e6a6ff92604b7b54f825c423dccf08529eb202194ac1052fbedb"
+python-versions = ">=3.8,<4"
+content-hash = "25ec60db7644950fc5bac3b8a08d4c220f835402d87974461bfd7255f44ff9bc"
diff --git a/pyproject.toml b/pyproject.toml
index 904b8d2..b8c4c53 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -18,17 +18,22 @@ classifiers = [
"Intended Audience :: Developers",
"Programming Language :: Python :: 3.8",
"Programming Language :: Python :: 3.9",
+ "Programming Language :: Python :: 3.10",
+ "Programming Language :: Python :: 3.11",
+ "Programming Language :: Python :: 3.12",
+ "Programming Language :: Python :: 3.13",
"Topic :: Utilities",
"Topic :: Software Development :: Libraries",
]
[tool.poetry.dependencies]
-python = "^3.8"
+python = ">=3.8,<4"
prompt-toolkit = ">=3.0.29"
PyYAML = {version = ">=5", optional = true }
validators = "^0.18.2"
pytz = "^2022.1"
tzlocal = "^4.1"
+importlib-metadata = "1.4"
[tool.poetry.extras]
yaml = ["PyYAML"]
@@ -40,13 +45,7 @@ pytest = ">=6.1.2,<8"
pytest-cov = ">=2.10.1,<5"
pytest-mock = "^3.3.1"
coverage = {extras = ["toml"], version = ">=5.3,<7"}
-flake8 = ">=3.8,<6"
-flake8-bugbear = ">=20,<23"
-flake8-cognitive-complexity = "^0.1"
-flake8-commas = "~2.0"
-flake8-future-import = "~0.4"
-flake8-import-order = "~0.18"
-flake8-broken-line = ">=0.3,<0.7"
+ruff = "0.3.*"
Sphinx = "^1.8.5"
sphinx-rtd-theme = "^1.0.0"
@@ -65,6 +64,7 @@ addopts = "--cov=interrogatio --cov-report=term-missing:skip-covered --cov-repor
[tool.coverage.run]
branch = true
+relative_files = true
[tool.coverage.report]
omit = [
@@ -79,3 +79,31 @@ exclude_lines = [
"raise NotImplementedError",
"if __name__ == .__main__.:",
]
+
+
+[tool.ruff]
+extend-exclude = [".vscode", ".devcontainer"]
+output-format = "full"
+
+[tool.ruff.lint]
+
+select = [
+ "E", # w errors
+ "W", # pycodestyle warnings
+ "F", # pyflakes
+ "I", # isort
+ "B", # flake8-bugbear
+ "C4", # flake8-comprehensions
+ "UP", # pyupgrade,
+ "PT", # flake8-pytest-style
+ "T10", # flake8-pytest-style
+]
+ignore = [
+ "PT004", # fixture '{name}' does not return anything, add leading underscore
+ "PT011", # pytest.raises({exception}) is too broad, set the match parameter or use a more specific exception
+ "B008", # do not perform function calls in argument defaults
+ "B904", # Within an `except` clause, raise exceptions with `raise ... from err` or `raise ... from None` to distinguish them from errors in exception handling
+]
+
+[tool.ruff.lint.pycodestyle]
+max-line-length = 100
\ No newline at end of file
diff --git a/sonar-project.properties b/sonar-project.properties
new file mode 100644
index 0000000..9ea7cbe
--- /dev/null
+++ b/sonar-project.properties
@@ -0,0 +1,13 @@
+sonar.projectKey=ffaraone_interrogatio
+sonar.organization=ffaraone
+
+sonar.language=py
+
+sonar.sources=interrogatio
+sonar.tests=tests
+sonar.inclusions=interrogatio/**
+sonar.exclusions=tests/**,Dockerfile
+
+sonar.python.coverage.reportPaths=coverage.xml
+sonar.python.xunit.reportPath=coverage.xml
+sonar.python.version=3
\ No newline at end of file
diff --git a/tests/conftest.py b/tests/conftest.py
index 186c1a0..cd22e1c 100644
--- a/tests/conftest.py
+++ b/tests/conftest.py
@@ -12,31 +12,31 @@
from interrogatio.validators.registry import _registry as v_registry
-@pytest.fixture
+@pytest.fixture()
def handlers_registry(mocker):
registry_copy = copy.deepcopy(h_registry)
registry_copy.clear()
mocker.patch(
- 'interrogatio.handlers.registry.get_registry',
+ "interrogatio.handlers.registry.get_registry",
return_value=registry_copy,
)
yield registry_copy
registry_copy.clear()
-@pytest.fixture
+@pytest.fixture()
def validators_registry(mocker):
registry_copy = copy.deepcopy(v_registry)
registry_copy.clear()
mocker.patch(
- 'interrogatio.validators.registry.get_registry',
+ "interrogatio.validators.registry.get_registry",
return_value=registry_copy,
)
yield registry_copy
registry_copy.clear()
-@pytest.fixture
+@pytest.fixture()
def test_handler():
class TestHandler(QHandler):
def get_layout(self):
@@ -57,7 +57,7 @@ def get_keybindings(self):
return TestHandler
-@pytest.fixture
+@pytest.fixture()
def mock_input():
with create_pipe_input() as pipe_input:
try:
diff --git a/tests/core/test_dialog.py b/tests/core/test_dialog.py
index 5c7bcf5..b77c080 100644
--- a/tests/core/test_dialog.py
+++ b/tests/core/test_dialog.py
@@ -2,80 +2,79 @@
def test_dialogus(mocker):
- mocked_set_theme = mocker.patch('interrogatio.core.dialog.set_theme')
- mocked_show_dialog = mocker.patch('interrogatio.core.dialog.show_dialog')
+ mocked_set_theme = mocker.patch("interrogatio.core.dialog.set_theme")
+ mocked_show_dialog = mocker.patch("interrogatio.core.dialog.show_dialog")
mocked_validate = mocker.patch(
- 'interrogatio.core.dialog.validate_questions',
+ "interrogatio.core.dialog.validate_questions",
)
- args = ([{'name': 'question1'}], 'title')
+ args = ([{"name": "question1"}], "title")
kwargs = {
- 'intro': 'intro',
- 'summary': True,
- 'fast_forward': False,
- 'next_text': 'next_text',
- 'previous_text': 'previous_text',
- 'cancel_text': 'cancel_text',
- 'finish_text': 'finish_text',
+ "intro": "intro",
+ "summary": True,
+ "fast_forward": False,
+ "next_text": "next_text",
+ "previous_text": "previous_text",
+ "cancel_text": "cancel_text",
+ "finish_text": "finish_text",
}
dialogus(*args, **kwargs)
- mocked_set_theme.assert_called_once_with('default')
+ mocked_set_theme.assert_called_once_with("default")
mocked_validate.assert_called_once_with(args[0])
mocked_show_dialog.assert_called_once_with(*args, **kwargs)
def test_show_dialog(mocker):
-
mocker.patch(
- 'interrogatio.core.dialog.for_dialog',
- return_value='a style',
+ "interrogatio.core.dialog.for_dialog",
+ return_value="a style",
)
mocked_handler = mocker.MagicMock()
- mocked_handler.get_answer.return_value = {'question': 'answer'}
+ mocked_handler.get_answer.return_value = {"question": "answer"}
mocked_handler.is_disabled.return_value = False
mocked_disabled_handler = mocker.MagicMock()
mocked_disabled_handler.is_disabled.return_value = True
mocker.patch(
- 'interrogatio.core.dialog.get_instance',
+ "interrogatio.core.dialog.get_instance",
side_effect=[mocked_handler, mocked_disabled_handler],
)
mocked_app = mocker.MagicMock()
mocked_app.run.return_value = True
mocked_app_cls = mocker.patch(
- 'interrogatio.core.dialog.Application',
+ "interrogatio.core.dialog.Application",
return_value=mocked_app,
)
mocked_wz = mocker.MagicMock()
mocked_wz_cls = mocker.patch(
- 'interrogatio.core.dialog.WizardDialog',
+ "interrogatio.core.dialog.WizardDialog",
return_value=mocked_wz,
)
mocked_layout = mocker.MagicMock()
mocked_layout_cls = mocker.patch(
- 'interrogatio.core.dialog.Layout',
+ "interrogatio.core.dialog.Layout",
return_value=mocked_layout,
)
- args = ([{'name': 'question'}, {'name': 'disabled_question'}], 'title')
+ args = ([{"name": "question"}, {"name": "disabled_question"}], "title")
kwargs = {
- 'intro': 'intro',
- 'summary': True,
- 'fast_forward': False,
- 'next_text': 'next_text',
- 'previous_text': 'previous_text',
- 'cancel_text': 'cancel_text',
- 'finish_text': 'finish_text',
+ "intro": "intro",
+ "summary": True,
+ "fast_forward": False,
+ "next_text": "next_text",
+ "previous_text": "previous_text",
+ "cancel_text": "cancel_text",
+ "finish_text": "finish_text",
}
answers = show_dialog(*args, **kwargs)
mocked_wz_cls.assert_called_once_with(
- 'title',
+ "title",
[mocked_handler, mocked_disabled_handler],
**kwargs,
)
@@ -83,45 +82,44 @@ def test_show_dialog(mocker):
mocked_app_cls.assert_called_once_with(
layout=mocked_layout,
mouse_support=False,
- style='a style',
+ style="a style",
full_screen=True,
)
- assert answers == {'question': 'answer'}
+ assert answers == {"question": "answer"}
def test_show_dialog_cancel(mocker):
-
mocker.patch(
- 'interrogatio.core.dialog.for_dialog',
+ "interrogatio.core.dialog.for_dialog",
)
mocked_handler = mocker.MagicMock()
mocker.patch(
- 'interrogatio.core.dialog.get_instance',
+ "interrogatio.core.dialog.get_instance",
return_value=mocked_handler,
)
mocked_app = mocker.MagicMock()
mocked_app.run.return_value = False
mocker.patch(
- 'interrogatio.core.dialog.Application',
+ "interrogatio.core.dialog.Application",
return_value=mocked_app,
)
mocker.patch(
- 'interrogatio.core.dialog.WizardDialog',
+ "interrogatio.core.dialog.WizardDialog",
)
mocker.patch(
- 'interrogatio.core.dialog.Layout',
+ "interrogatio.core.dialog.Layout",
)
- args = ([{'name': 'question1'}], 'title')
+ args = ([{"name": "question1"}], "title")
kwargs = {
- 'intro': 'intro',
- 'summary': True,
- 'next_text': 'next_text',
- 'previous_text': 'previous_text',
- 'cancel_text': 'cancel_text',
- 'finish_text': 'finish_text',
+ "intro": "intro",
+ "summary": True,
+ "next_text": "next_text",
+ "previous_text": "previous_text",
+ "cancel_text": "cancel_text",
+ "finish_text": "finish_text",
}
answers = show_dialog(*args, **kwargs)
diff --git a/tests/core/test_prompt.py b/tests/core/test_prompt.py
index 3e4ebf5..601b59f 100644
--- a/tests/core/test_prompt.py
+++ b/tests/core/test_prompt.py
@@ -9,31 +9,31 @@
def test_string_handler(mock_input):
questions = [
{
- 'name': 'question',
- 'type': 'input',
- 'message': 'message',
- 'description': 'description',
+ "name": "question",
+ "type": "input",
+ "message": "message",
+ "description": "description",
},
]
- mock_input.send_text('this is the answer\n')
+ mock_input.send_text("this is the answer\n")
answers = interrogatio(questions)
- assert 'question' in answers
- assert answers['question'] == 'this is the answer'
+ assert "question" in answers
+ assert answers["question"] == "this is the answer"
def test_string_handler_ctrl_c(mock_input):
questions = [
{
- 'name': 'question',
- 'type': 'input',
- 'message': 'message',
- 'description': 'description',
+ "name": "question",
+ "type": "input",
+ "message": "message",
+ "description": "description",
},
]
- mock_input.send_text('\x03')
+ mock_input.send_text("\x03")
answers = interrogatio(questions)
assert answers is None
@@ -42,25 +42,25 @@ def test_string_handler_ctrl_c(mock_input):
def test_string_handler_invalid(mocker, mock_input):
questions = [
{
- 'name': 'question',
- 'type': 'input',
- 'message': 'message',
- 'description': 'description',
- 'validators': [{'name': 'required'}],
+ "name": "question",
+ "type": "input",
+ "message": "message",
+ "description": "description",
+ "validators": [{"name": "required"}],
},
]
mocked_style = mocker.MagicMock()
mocker.patch(
- 'interrogatio.core.prompt.for_prompt',
+ "interrogatio.core.prompt.for_prompt",
return_value=mocked_style,
)
mocked_text = mocker.MagicMock()
mocked_formatted_text = mocker.patch(
- 'interrogatio.core.prompt.FormattedText',
+ "interrogatio.core.prompt.FormattedText",
return_value=mocked_text,
)
- mocked_print = mocker.patch('interrogatio.core.prompt.print_formatted_text')
- mock_input.send_text('\n\x03')
+ mocked_print = mocker.patch("interrogatio.core.prompt.print_formatted_text")
+ mock_input.send_text("\n\x03")
interrogatio(questions)
mocked_print.assert_called_once_with(
@@ -69,38 +69,38 @@ def test_string_handler_invalid(mocker, mock_input):
)
mocked_formatted_text.assert_called_once_with(
- [('class:error', 'this field is required')],
+ [("class:error", "this field is required")],
)
def test_password_handler(mock_input):
questions = [
{
- 'name': 'question',
- 'type': 'password',
- 'message': 'message',
- 'description': 'description',
+ "name": "question",
+ "type": "password",
+ "message": "message",
+ "description": "description",
},
]
- mock_input.send_text('mypassword\n')
+ mock_input.send_text("mypassword\n")
answers = interrogatio(questions)
- assert 'question' in answers
- assert answers['question'] == 'mypassword'
+ assert "question" in answers
+ assert answers["question"] == "mypassword"
def test_password_handler_ctrl_c(mock_input):
questions = [
{
- 'name': 'question',
- 'type': 'password',
- 'message': 'message',
- 'description': 'description',
+ "name": "question",
+ "type": "password",
+ "message": "message",
+ "description": "description",
},
]
- mock_input.send_text('\x03')
+ mock_input.send_text("\x03")
answers = interrogatio(questions)
assert answers is None
@@ -109,25 +109,25 @@ def test_password_handler_ctrl_c(mock_input):
def test_password_handler_invalid(mocker, mock_input):
questions = [
{
- 'name': 'question',
- 'type': 'password',
- 'message': 'message',
- 'description': 'description',
- 'validators': [{'name': 'required'}],
+ "name": "question",
+ "type": "password",
+ "message": "message",
+ "description": "description",
+ "validators": [{"name": "required"}],
},
]
mocked_style = mocker.MagicMock()
mocker.patch(
- 'interrogatio.core.prompt.for_prompt',
+ "interrogatio.core.prompt.for_prompt",
return_value=mocked_style,
)
mocked_text = mocker.MagicMock()
mocked_formatted_text = mocker.patch(
- 'interrogatio.core.prompt.FormattedText',
+ "interrogatio.core.prompt.FormattedText",
return_value=mocked_text,
)
- mocked_print = mocker.patch('interrogatio.core.prompt.print_formatted_text')
- mock_input.send_text('\n\x03')
+ mocked_print = mocker.patch("interrogatio.core.prompt.print_formatted_text")
+ mock_input.send_text("\n\x03")
interrogatio(questions)
mocked_print.assert_called_once_with(
@@ -136,181 +136,181 @@ def test_password_handler_invalid(mocker, mock_input):
)
mocked_formatted_text.assert_called_once_with(
- [('class:error', 'this field is required')],
+ [("class:error", "this field is required")],
)
def test_selectone_handler(mock_input):
questions = [
{
- 'name': 'question',
- 'type': 'selectone',
- 'message': 'message',
- 'description': 'description',
- 'values': [
- ('first', 'First'),
- ('second', 'Second'),
- ('third', 'Third'),
+ "name": "question",
+ "type": "selectone",
+ "message": "message",
+ "description": "description",
+ "values": [
+ ("first", "First"),
+ ("second", "Second"),
+ ("third", "Third"),
],
},
]
- mock_input.send_text('\x1b[B ' + chr(13))
+ mock_input.send_text("\x1b[B " + chr(13))
answers = interrogatio(questions)
- assert 'question' in answers
- assert answers['question'] == 'second'
+ assert "question" in answers
+ assert answers["question"] == "second"
def test_selectone_handler_up(mock_input):
questions = [
{
- 'name': 'question',
- 'type': 'selectone',
- 'message': 'message',
- 'description': 'description',
- 'values': [
- ('first', 'First'),
- ('second', 'Second'),
- ('third', 'Third'),
+ "name": "question",
+ "type": "selectone",
+ "message": "message",
+ "description": "description",
+ "values": [
+ ("first", "First"),
+ ("second", "Second"),
+ ("third", "Third"),
],
},
]
- mock_input.send_text('\x1b[B\x1b[A ' + chr(13))
+ mock_input.send_text("\x1b[B\x1b[A " + chr(13))
answers = interrogatio(questions)
- assert 'question' in answers
- assert answers['question'] == 'first'
+ assert "question" in answers
+ assert answers["question"] == "first"
def test_selectone_handler_page_down(mock_input):
questions = [
{
- 'name': 'question',
- 'type': 'selectone',
- 'message': 'message',
- 'description': 'description',
- 'values': [
- ('first', 'First'),
- ('second', 'Second'),
- ('third', 'Third'),
+ "name": "question",
+ "type": "selectone",
+ "message": "message",
+ "description": "description",
+ "values": [
+ ("first", "First"),
+ ("second", "Second"),
+ ("third", "Third"),
],
},
]
- mock_input.send_text('\x1b[6~ ' + chr(13))
+ mock_input.send_text("\x1b[6~ " + chr(13))
answers = interrogatio(questions)
- assert 'question' in answers
- assert answers['question'] == 'third'
+ assert "question" in answers
+ assert answers["question"] == "third"
def test_selectone_handler_page_up(mock_input):
questions = [
{
- 'name': 'question',
- 'type': 'selectone',
- 'message': 'message',
- 'description': 'description',
- 'values': [
- ('first', 'First'),
- ('second', 'Second'),
- ('third', 'Third'),
+ "name": "question",
+ "type": "selectone",
+ "message": "message",
+ "description": "description",
+ "values": [
+ ("first", "First"),
+ ("second", "Second"),
+ ("third", "Third"),
],
},
]
- mock_input.send_text('\x1b[6~\x1b[5~ ' + chr(13))
+ mock_input.send_text("\x1b[6~\x1b[5~ " + chr(13))
answers = interrogatio(questions)
- assert 'question' in answers
- assert answers['question'] == 'first'
+ assert "question" in answers
+ assert answers["question"] == "first"
def test_selectone_handler_value_initial(mock_input):
questions = [
{
- 'name': 'question',
- 'type': 'selectone',
- 'message': 'message',
- 'description': 'description',
- 'values': [
- ('first', 'First'),
- ('second', 'Second'),
- ('third', 'Third'),
+ "name": "question",
+ "type": "selectone",
+ "message": "message",
+ "description": "description",
+ "values": [
+ ("first", "First"),
+ ("second", "Second"),
+ ("third", "Third"),
],
},
]
- mock_input.send_text('T ' + chr(13))
+ mock_input.send_text("T " + chr(13))
answers = interrogatio(questions)
- assert 'question' in answers
- assert answers['question'] == 'third'
+ assert "question" in answers
+ assert answers["question"] == "third"
def test_selectone_handler_value_initial_not_found(mock_input):
questions = [
{
- 'name': 'question',
- 'type': 'selectone',
- 'message': 'message',
- 'description': 'description',
- 'values': [
- ('first', 'First'),
- ('second', 'Second'),
- ('third', 'Third'),
+ "name": "question",
+ "type": "selectone",
+ "message": "message",
+ "description": "description",
+ "values": [
+ ("first", "First"),
+ ("second", "Second"),
+ ("third", "Third"),
],
},
]
- mock_input.send_text('Z ' + chr(13))
+ mock_input.send_text("Z " + chr(13))
answers = interrogatio(questions)
- assert 'question' in answers
- assert answers['question'] == 'first'
+ assert "question" in answers
+ assert answers["question"] == "first"
def test_selectone_handler_with_default(mock_input):
questions = [
{
- 'name': 'question',
- 'type': 'selectone',
- 'message': 'message',
- 'description': 'description',
- 'values': [
- ('first', 'First'),
- ('second', 'Second'),
- ('third', 'Third'),
+ "name": "question",
+ "type": "selectone",
+ "message": "message",
+ "description": "description",
+ "values": [
+ ("first", "First"),
+ ("second", "Second"),
+ ("third", "Third"),
],
- 'default': 'third',
+ "default": "third",
},
]
mock_input.send_text(chr(13))
answers = interrogatio(questions)
- assert 'question' in answers
- assert answers['question'] == 'third'
+ assert "question" in answers
+ assert answers["question"] == "third"
def test_selectone_handler_ctrl_c(mock_input):
questions = [
{
- 'name': 'question',
- 'type': 'selectone',
- 'message': 'message',
- 'description': 'description',
- 'values': [
- ('first', 'First'),
- ('second', 'Second'),
- ('third', 'Third'),
+ "name": "question",
+ "type": "selectone",
+ "message": "message",
+ "description": "description",
+ "values": [
+ ("first", "First"),
+ ("second", "Second"),
+ ("third", "Third"),
],
},
]
- mock_input.send_text('\x03')
+ mock_input.send_text("\x03")
answers = interrogatio(questions)
assert answers is None
@@ -319,240 +319,240 @@ def test_selectone_handler_ctrl_c(mock_input):
def test_selectmany_handler(mock_input):
questions = [
{
- 'name': 'question',
- 'type': 'selectmany',
- 'message': 'message',
- 'description': 'description',
- 'values': [
- ('first', 'First'),
- ('second', 'Second'),
- ('third', 'Third'),
+ "name": "question",
+ "type": "selectmany",
+ "message": "message",
+ "description": "description",
+ "values": [
+ ("first", "First"),
+ ("second", "Second"),
+ ("third", "Third"),
],
},
]
- mock_input.send_text('\t\t \x1b[B ' + chr(13))
+ mock_input.send_text("\t\t \x1b[B " + chr(13))
answers = interrogatio(questions)
- assert 'question' in answers
- assert sorted(answers['question']) == sorted(['first', 'second'])
+ assert "question" in answers
+ assert sorted(answers["question"]) == sorted(["first", "second"])
def test_selectmany_handler_with_checked(mock_input):
questions = [
{
- 'name': 'question',
- 'type': 'selectmany',
- 'message': 'message',
- 'description': 'description',
- 'values': [
- ('first', 'First'),
- ('second', 'Second'),
- ('third', 'Third'),
+ "name": "question",
+ "type": "selectmany",
+ "message": "message",
+ "description": "description",
+ "values": [
+ ("first", "First"),
+ ("second", "Second"),
+ ("third", "Third"),
],
- 'default': {'first', 'third'},
+ "default": {"first", "third"},
},
]
- mock_input.send_text('\t\t' + chr(13))
+ mock_input.send_text("\t\t" + chr(13))
answers = interrogatio(questions)
- assert 'question' in answers
- assert sorted(answers['question']) == sorted(['first', 'third'])
+ assert "question" in answers
+ assert sorted(answers["question"]) == sorted(["first", "third"])
def test_selectmany_handler_check_uncheck(mock_input):
questions = [
{
- 'name': 'question',
- 'type': 'selectmany',
- 'message': 'message',
- 'description': 'description',
- 'values': [
- ('first', 'First'),
- ('second', 'Second'),
- ('third', 'Third'),
+ "name": "question",
+ "type": "selectmany",
+ "message": "message",
+ "description": "description",
+ "values": [
+ ("first", "First"),
+ ("second", "Second"),
+ ("third", "Third"),
],
},
]
- mock_input.send_text('\t\t ' + chr(13))
+ mock_input.send_text("\t\t " + chr(13))
answers = interrogatio(questions)
- assert 'question' in answers
- assert answers['question'] == []
+ assert "question" in answers
+ assert answers["question"] == []
def test_selectmany_handler_up(mock_input):
questions = [
{
- 'name': 'question',
- 'type': 'selectmany',
- 'message': 'message',
- 'description': 'description',
- 'values': [
- ('first', 'First'),
- ('second', 'Second'),
- ('third', 'Third'),
+ "name": "question",
+ "type": "selectmany",
+ "message": "message",
+ "description": "description",
+ "values": [
+ ("first", "First"),
+ ("second", "Second"),
+ ("third", "Third"),
],
},
]
- mock_input.send_text('\t\t \x1b[B \x1b[A ' + chr(13))
+ mock_input.send_text("\t\t \x1b[B \x1b[A " + chr(13))
answers = interrogatio(questions)
- assert 'question' in answers
- assert answers['question'] == ['second']
+ assert "question" in answers
+ assert answers["question"] == ["second"]
def test_selectmany_handler_page_down(mock_input):
questions = [
{
- 'name': 'question',
- 'type': 'selectmany',
- 'message': 'message',
- 'description': 'description',
- 'values': [
- ('first', 'First'),
- ('second', 'Second'),
- ('third', 'Third'),
+ "name": "question",
+ "type": "selectmany",
+ "message": "message",
+ "description": "description",
+ "values": [
+ ("first", "First"),
+ ("second", "Second"),
+ ("third", "Third"),
],
},
]
- mock_input.send_text('\t\t\x1b[6~ ' + chr(13))
+ mock_input.send_text("\t\t\x1b[6~ " + chr(13))
answers = interrogatio(questions)
- assert 'question' in answers
- assert answers['question'] == ['third']
+ assert "question" in answers
+ assert answers["question"] == ["third"]
def test_selectmany_handler_page_up(mock_input):
questions = [
{
- 'name': 'question',
- 'type': 'selectmany',
- 'message': 'message',
- 'description': 'description',
- 'values': [
- ('first', 'First'),
- ('second', 'Second'),
- ('third', 'Third'),
+ "name": "question",
+ "type": "selectmany",
+ "message": "message",
+ "description": "description",
+ "values": [
+ ("first", "First"),
+ ("second", "Second"),
+ ("third", "Third"),
],
},
]
- mock_input.send_text('\t\t\x1b[6~\x1b[5~ ' + chr(13))
+ mock_input.send_text("\t\t\x1b[6~\x1b[5~ " + chr(13))
answers = interrogatio(questions)
- assert 'question' in answers
- assert answers['question'] == ['first']
+ assert "question" in answers
+ assert answers["question"] == ["first"]
def test_selectmany_handler_initial(mock_input):
questions = [
{
- 'name': 'question',
- 'type': 'selectmany',
- 'message': 'message',
- 'description': 'description',
- 'values': [
- ('first', 'First'),
- ('second', 'Second'),
- ('third', 'Third'),
+ "name": "question",
+ "type": "selectmany",
+ "message": "message",
+ "description": "description",
+ "values": [
+ ("first", "First"),
+ ("second", "Second"),
+ ("third", "Third"),
],
},
]
- mock_input.send_text('\t\tS T ' + chr(13))
+ mock_input.send_text("\t\tS T " + chr(13))
answers = interrogatio(questions)
- assert 'question' in answers
- assert sorted(answers['question']) == sorted(['second', 'third'])
+ assert "question" in answers
+ assert sorted(answers["question"]) == sorted(["second", "third"])
def test_selectmany_handler_initial_not_found(mock_input):
questions = [
{
- 'name': 'question',
- 'type': 'selectmany',
- 'message': 'message',
- 'description': 'description',
- 'values': [
- ('first', 'First'),
- ('second', 'Second'),
- ('third', 'Third'),
+ "name": "question",
+ "type": "selectmany",
+ "message": "message",
+ "description": "description",
+ "values": [
+ ("first", "First"),
+ ("second", "Second"),
+ ("third", "Third"),
],
},
]
- mock_input.send_text('\t\tZ' + chr(13))
+ mock_input.send_text("\t\tZ" + chr(13))
answers = interrogatio(questions)
- assert 'question' in answers
- assert answers['question'] == []
+ assert "question" in answers
+ assert answers["question"] == []
def test_selectmany_handler_select_all(mock_input):
questions = [
{
- 'name': 'question',
- 'type': 'selectmany',
- 'message': 'message',
- 'description': 'description',
- 'values': [
- ('first', 'First'),
- ('second', 'Second'),
- ('third', 'Third'),
+ "name": "question",
+ "type": "selectmany",
+ "message": "message",
+ "description": "description",
+ "values": [
+ ("first", "First"),
+ ("second", "Second"),
+ ("third", "Third"),
],
},
]
- mock_input.send_text(' \t\t' + chr(13))
+ mock_input.send_text(" \t\t" + chr(13))
answers = interrogatio(questions)
- assert 'question' in answers
- assert sorted(answers['question']) == sorted(['first', 'second', 'third'])
+ assert "question" in answers
+ assert sorted(answers["question"]) == sorted(["first", "second", "third"])
def test_selectmany_handler_select_none(mock_input):
questions = [
{
- 'name': 'question',
- 'type': 'selectmany',
- 'message': 'message',
- 'description': 'description',
- 'values': [
- ('first', 'First'),
- ('second', 'Second'),
- ('third', 'Third'),
+ "name": "question",
+ "type": "selectmany",
+ "message": "message",
+ "description": "description",
+ "values": [
+ ("first", "First"),
+ ("second", "Second"),
+ ("third", "Third"),
],
},
]
- mock_input.send_text(' \t \t' + chr(13))
+ mock_input.send_text(" \t \t" + chr(13))
answers = interrogatio(questions)
- assert 'question' in answers
- assert answers['question'] == []
+ assert "question" in answers
+ assert answers["question"] == []
def test_selectmany_handler_ctrl_c(mock_input):
questions = [
{
- 'name': 'question',
- 'type': 'selectmany',
- 'message': 'message',
- 'description': 'description',
- 'values': [
- ('first', 'First'),
- ('second', 'Second'),
- ('third', 'Third'),
+ "name": "question",
+ "type": "selectmany",
+ "message": "message",
+ "description": "description",
+ "values": [
+ ("first", "First"),
+ ("second", "Second"),
+ ("third", "Third"),
],
},
]
- mock_input.send_text('\x03')
+ mock_input.send_text("\x03")
answers = interrogatio(questions)
assert answers is None
@@ -561,18 +561,18 @@ def test_selectmany_handler_ctrl_c(mock_input):
def test_date_handler(mock_input):
questions = [
{
- 'name': 'question',
- 'type': 'date',
- 'message': 'message',
- 'description': 'description',
+ "name": "question",
+ "type": "date",
+ "message": "message",
+ "description": "description",
},
]
- mock_input.send_text('20200101' + chr(13))
+ mock_input.send_text("20200101" + chr(13))
answers = interrogatio(questions)
- assert 'question' in answers
- assert answers['question'] == datetime(
+ assert "question" in answers
+ assert answers["question"] == datetime(
2020,
1,
1,
@@ -583,20 +583,20 @@ def test_date_handler(mock_input):
def test_date_handler_go_previous(mock_input):
questions = [
{
- 'name': 'question',
- 'type': 'date',
- 'message': 'message',
- 'description': 'description',
+ "name": "question",
+ "type": "date",
+ "message": "message",
+ "description": "description",
},
]
mock_input.send_text(
- '20200101' + chr(127) + chr(127) + chr(127) + '201' + chr(13),
+ "20200101" + chr(127) + chr(127) + chr(127) + "201" + chr(13),
)
answers = interrogatio(questions)
- assert 'question' in answers
- assert answers['question'] == datetime(
+ assert "question" in answers
+ assert answers["question"] == datetime(
2020,
2,
1,
@@ -607,20 +607,20 @@ def test_date_handler_go_previous(mock_input):
def test_date_handler_go_previous_beginning(mock_input):
questions = [
{
- 'name': 'question',
- 'type': 'date',
- 'message': 'message',
- 'description': 'description',
+ "name": "question",
+ "type": "date",
+ "message": "message",
+ "description": "description",
},
]
mock_input.send_text(
- '20200101' + chr(127) * 9 + '20220706' + chr(13),
+ "20200101" + chr(127) * 9 + "20220706" + chr(13),
)
answers = interrogatio(questions)
- assert 'question' in answers
- assert answers['question'] == datetime(
+ assert "question" in answers
+ assert answers["question"] == datetime(
2022,
7,
6,
@@ -631,53 +631,53 @@ def test_date_handler_go_previous_beginning(mock_input):
def test_date_handler_no_value(mock_input):
questions = [
{
- 'name': 'question',
- 'type': 'date',
- 'message': 'message',
- 'description': 'description',
+ "name": "question",
+ "type": "date",
+ "message": "message",
+ "description": "description",
},
]
mock_input.send_text(chr(13))
answers = interrogatio(questions)
- assert 'question' in answers
- assert answers['question'] is None
+ assert "question" in answers
+ assert answers["question"] is None
def test_date_handler_invalid_char(mock_input):
questions = [
{
- 'name': 'question',
- 'type': 'date',
- 'message': 'message',
- 'description': 'description',
- 'disabled': False,
+ "name": "question",
+ "type": "date",
+ "message": "message",
+ "description": "description",
+ "disabled": False,
},
]
- mock_input.send_text('**##**@@' + chr(13))
+ mock_input.send_text("**##**@@" + chr(13))
answers = interrogatio(questions)
- assert 'question' in answers
- assert answers['question'] is None
+ assert "question" in answers
+ assert answers["question"] is None
def test_date_handler_exceed_length(mock_input):
questions = [
{
- 'name': 'question',
- 'type': 'date',
- 'message': 'message',
- 'description': 'description',
+ "name": "question",
+ "type": "date",
+ "message": "message",
+ "description": "description",
},
]
- mock_input.send_text('2020010101' + chr(13))
+ mock_input.send_text("2020010101" + chr(13))
answers = interrogatio(questions)
- assert 'question' in answers
- assert answers['question'] == datetime(
+ assert "question" in answers
+ assert answers["question"] == datetime(
2020,
1,
1,
@@ -688,34 +688,34 @@ def test_date_handler_exceed_length(mock_input):
def test_daterange_handler(mock_input):
questions = [
{
- 'name': 'question',
- 'type': 'daterange',
- 'message': 'message',
- 'description': 'description',
+ "name": "question",
+ "type": "daterange",
+ "message": "message",
+ "description": "description",
},
]
- mock_input.send_text('20200101\t20210101' + chr(13))
+ mock_input.send_text("20200101\t20210101" + chr(13))
answers = interrogatio(questions)
- assert 'question' in answers
- assert answers['question'] == {
- 'from': datetime(2020, 1, 1, tzinfo=timezone.utc),
- 'to': datetime(2021, 1, 1, tzinfo=timezone.utc),
+ assert "question" in answers
+ assert answers["question"] == {
+ "from": datetime(2020, 1, 1, tzinfo=timezone.utc),
+ "to": datetime(2021, 1, 1, tzinfo=timezone.utc),
}
def test_disabled_handler(mock_input):
questions = [
{
- 'name': 'question',
- 'type': 'input',
- 'message': 'message',
- 'description': 'description',
- 'disabled': True,
+ "name": "question",
+ "type": "input",
+ "message": "message",
+ "description": "description",
+ "disabled": True,
},
]
- mock_input.send_text('this is the answer\n')
+ mock_input.send_text("this is the answer\n")
answers = interrogatio(questions)
assert len(answers) == 0
@@ -724,17 +724,17 @@ def test_disabled_handler(mock_input):
def test_disabled_handler_invalid(mock_input):
questions = [
{
- 'name': 'question',
- 'type': 'input',
- 'message': 'message',
- 'description': 'description',
- 'disabled': 'not callable or boolean',
+ "name": "question",
+ "type": "input",
+ "message": "message",
+ "description": "description",
+ "disabled": "not callable or boolean",
},
]
- mock_input.send_text('this is the answer\n')
+ mock_input.send_text("this is the answer\n")
with pytest.raises(InvalidQuestionError) as cv:
interrogatio(questions)
- assert str(cv.value) == 'Disabled flag must be a boolean or callable.'
+ assert str(cv.value) == "Disabled flag must be a boolean or callable."
diff --git a/tests/handlers/test_base.py b/tests/handlers/test_base.py
index 65442ce..d553fe7 100644
--- a/tests/handlers/test_base.py
+++ b/tests/handlers/test_base.py
@@ -3,39 +3,43 @@
def test_qhandler_errors(test_handler):
t = test_handler({})
- t._errors = ['a', 'b', 'c']
- assert t.errors == ['a', 'b', 'c']
+ t._errors = ["a", "b", "c"]
+ assert t.errors == ["a", "b", "c"]
def test_qhandler_get_init_extra_args(test_handler):
- t = test_handler({'extra_args': {'a': 0, 'b': '1'}})
- assert t.get_init_extra_args() == {'a': 0, 'b': '1'}
+ t = test_handler({"extra_args": {"a": 0, "b": "1"}})
+ assert t.get_init_extra_args() == {"a": 0, "b": "1"}
def test_qhandler_get_answer(mocker, test_handler):
- t = test_handler({'name': 'test_field'})
- t.get_value = mocker.MagicMock(return_value='test_value')
- assert t.get_answer() == {'test_field': 'test_value'}
+ t = test_handler({"name": "test_field"})
+ t.get_value = mocker.MagicMock(return_value="test_value")
+ assert t.get_answer() == {"test_field": "test_value"}
def test_qhandler_get_variable_name(test_handler):
- t = test_handler({'name': 'test_field'})
- assert t.get_variable_name() == 'test_field'
+ t = test_handler({"name": "test_field"})
+ assert t.get_variable_name() == "test_field"
def test_qhandler_is_valid_valid(mocker, test_handler):
- t = test_handler({
- 'name': 'test_field',
- 'validators': [RequiredValidator()],
- })
- t.get_value = mocker.MagicMock(return_value='value')
+ t = test_handler(
+ {
+ "name": "test_field",
+ "validators": [RequiredValidator()],
+ }
+ )
+ t.get_value = mocker.MagicMock(return_value="value")
assert t.is_valid() is True
def test_qhandler_is_valid_invalid(mocker, test_handler):
- t = test_handler({
- 'name': 'test_field',
- 'validators': [RequiredValidator()],
- })
- t.get_value = mocker.MagicMock(return_value='')
+ t = test_handler(
+ {
+ "name": "test_field",
+ "validators": [RequiredValidator()],
+ }
+ )
+ t.get_value = mocker.MagicMock(return_value="")
assert t.is_valid() is False
diff --git a/tests/handlers/test_builtins.py b/tests/handlers/test_builtins.py
index c511eb6..837371b 100644
--- a/tests/handlers/test_builtins.py
+++ b/tests/handlers/test_builtins.py
@@ -19,8 +19,8 @@
@pytest.mark.parametrize(
- ('handler', 'expected_widget'),
- (
+ ("handler", "expected_widget"),
+ [
(StringHandler, TextArea),
(PasswordHandler, TextArea),
(SelectOneHandler, SelectOne),
@@ -28,7 +28,7 @@
(MaskedInputHandler, MaskedInput),
(DateHandler, MaskedInput),
(DateRangeHandler, DateRange),
- ),
+ ],
)
def test_handler_get_widget_class(handler, expected_widget):
s = handler({})
@@ -36,11 +36,11 @@ def test_handler_get_widget_class(handler, expected_widget):
@pytest.mark.parametrize(
- ('handler', 'expected_widget'),
- (
+ ("handler", "expected_widget"),
+ [
(StringHandler, TextArea),
(PasswordHandler, TextArea),
- ),
+ ],
)
def test_handler_get_widget(handler, expected_widget):
question = {}
@@ -49,33 +49,33 @@ def test_handler_get_widget(handler, expected_widget):
@pytest.mark.parametrize(
- 'handler',
- (
+ "handler",
+ [
StringHandler,
PasswordHandler,
- ),
+ ],
)
def test_textarea_handler_get_layout_cursor_position(handler):
question = {}
s = handler(question)
widget = s.get_widget()
- widget.text = 'this is the text'
+ widget.text = "this is the text"
s.get_layout()
assert widget.buffer.cursor_position == len(widget.text)
@pytest.mark.parametrize(
- 'handler',
- (
+ "handler",
+ [
StringHandler,
PasswordHandler,
- ),
+ ],
)
def test_textarea_handler_get_layout(handler):
question = {}
s = handler(question)
widget = s.get_widget()
- widget.text = 'This is the widget text'
+ widget.text = "This is the widget text"
layout = s.get_layout()
assert isinstance(layout, HSplit)
assert len(layout.children) == 1
@@ -85,21 +85,21 @@ def test_textarea_handler_get_layout(handler):
assert layout.children[0].padding == 1
input_ctrl = layout.children[0].children[0]
assert isinstance(input_ctrl, Window)
- assert input_ctrl.content.buffer.text == 'This is the widget text'
+ assert input_ctrl.content.buffer.text == "This is the widget text"
@pytest.mark.parametrize(
- 'handler',
- (
+ "handler",
+ [
StringHandler,
PasswordHandler,
- ),
+ ],
)
def test_textarea_handler_get_layout_with_msg(handler):
- question = {'message': 'this is a message'}
+ question = {"message": "this is a message"}
s = handler(question)
widget = s.get_widget()
- widget.text = 'This is the widget text'
+ widget.text = "This is the widget text"
layout = s.get_layout()
assert isinstance(layout, HSplit)
assert len(layout.children) == 1
@@ -109,44 +109,44 @@ def test_textarea_handler_get_layout_with_msg(handler):
assert layout.children[0].padding == 1
label_ctrl = layout.children[0].children[0]
assert isinstance(label_ctrl, Window)
- assert label_ctrl.content.text() == 'this is a message'
+ assert label_ctrl.content.text() == "this is a message"
input_ctrl = layout.children[0].children[1]
- assert input_ctrl.content.buffer.text == 'This is the widget text'
+ assert input_ctrl.content.buffer.text == "This is the widget text"
@pytest.mark.parametrize(
- 'handler',
- (
+ "handler",
+ [
StringHandler,
PasswordHandler,
- ),
+ ],
)
def test_textarea_handler_get_layout_with_description(handler):
- question = {'description': 'this is a description'}
+ question = {"description": "this is a description"}
s = handler(question)
widget = s.get_widget()
- widget.text = 'This is the widget text'
+ widget.text = "This is the widget text"
layout = s.get_layout()
assert isinstance(layout, HSplit)
assert len(layout.children) == 2
assert layout.padding == 1
label_ctrl = layout.children[0]
assert isinstance(label_ctrl, Window)
- assert label_ctrl.content.text[0][1] == 'this is a description'
+ assert label_ctrl.content.text[0][1] == "this is a description"
assert isinstance(layout.children[1], VSplit)
assert len(layout.children[1].children) == 1
assert layout.children[1].padding == 1
input_ctrl = layout.children[1].children[0]
- assert input_ctrl.content.buffer.text == 'This is the widget text'
+ assert input_ctrl.content.buffer.text == "This is the widget text"
@pytest.mark.parametrize(
- 'handler',
- (
+ "handler",
+ [
StringHandler,
PasswordHandler,
- ),
+ ],
)
def test_textarea_handler_get_keybindings(handler):
s = handler({})
@@ -157,37 +157,37 @@ def test_textarea_handler_get_keybindings(handler):
@pytest.mark.parametrize(
- 'handler',
- (
+ "handler",
+ [
StringHandler,
PasswordHandler,
- ),
+ ],
)
def test_textarea_handler_get_value(mocker, handler):
s = handler({})
widget_mock = mocker.MagicMock()
- widget_mock.text = 'Test text'
+ widget_mock.text = "Test text"
s.get_widget = mocker.MagicMock(return_value=widget_mock)
- assert s.get_value() == 'Test text'
+ assert s.get_value() == "Test text"
@pytest.mark.parametrize(
- ('question', 'expected'),
- (
+ ("question", "expected"),
+ [
(
- {'default': 'default_text'},
+ {"default": "default_text"},
{
- 'multiline': False,
- 'text': 'default_text',
- 'style': 'class:input.answer',
+ "multiline": False,
+ "text": "default_text",
+ "style": "class:input.answer",
},
),
(
- {'multiline': True},
- {'multiline': True, 'style': 'class:input.answer'},
+ {"multiline": True},
+ {"multiline": True, "style": "class:input.answer"},
),
- ),
+ ],
)
def test_string_handler_get_widget_init_kwargs(question, expected):
s = StringHandler(question)
@@ -195,26 +195,26 @@ def test_string_handler_get_widget_init_kwargs(question, expected):
@pytest.mark.parametrize(
- ('question', 'expected'),
- (
+ ("question", "expected"),
+ [
(
- {'default': 'default_text'},
+ {"default": "default_text"},
{
- 'text': 'default_text',
- 'style': 'class:password.answer',
- 'password': True,
- 'multiline': False,
+ "text": "default_text",
+ "style": "class:password.answer",
+ "password": True,
+ "multiline": False,
},
),
(
{},
{
- 'multiline': False,
- 'style': 'class:password.answer',
- 'password': True,
+ "multiline": False,
+ "style": "class:password.answer",
+ "password": True,
},
),
- ),
+ ],
)
def test_password_handler_get_widget_init_kwargs(question, expected):
s = PasswordHandler(question)
@@ -222,7 +222,7 @@ def test_password_handler_get_widget_init_kwargs(question, expected):
def test_selectone_handler_get_layout():
- question = {'values': [('a', 'A')]}
+ question = {"values": [("a", "A")]}
s = SelectOneHandler(question)
layout = s.get_layout()
assert isinstance(layout, HSplit)
@@ -236,7 +236,7 @@ def test_selectone_handler_get_layout():
def test_selectone_handler_get_layout_with_msg():
- question = {'message': 'this is a message', 'values': [('a', 'A')]}
+ question = {"message": "this is a message", "values": [("a", "A")]}
s = SelectOneHandler(question)
layout = s.get_layout()
assert isinstance(layout, HSplit)
@@ -247,13 +247,13 @@ def test_selectone_handler_get_layout_with_msg():
assert layout.children[0].padding == 1
label_ctrl = layout.children[0].children[0]
assert isinstance(label_ctrl, Window)
- assert label_ctrl.content.text() == 'this is a message'
+ assert label_ctrl.content.text() == "this is a message"
input_ctrl = layout.children[0].children[1]
assert isinstance(input_ctrl, Window)
def test_selectone_handler_get_layout_with_description():
- question = {'description': 'this is a description', 'values': [('a', 'A')]}
+ question = {"description": "this is a description", "values": [("a", "A")]}
s = SelectOneHandler(question)
layout = s.get_layout()
assert isinstance(layout, HSplit)
@@ -261,7 +261,7 @@ def test_selectone_handler_get_layout_with_description():
assert layout.padding == 1
label_ctrl = layout.children[0]
assert isinstance(label_ctrl, Window)
- assert label_ctrl.content.text[0][1] == 'this is a description'
+ assert label_ctrl.content.text[0][1] == "this is a description"
assert isinstance(layout.children[1], VSplit)
assert len(layout.children[1].children) == 1
@@ -271,24 +271,24 @@ def test_selectone_handler_get_layout_with_description():
@pytest.mark.parametrize(
- ('question', 'expected'),
- (
+ ("question", "expected"),
+ [
(
- {'default': 'default_value', 'values': [('a', 'A')]},
+ {"default": "default_value", "values": [("a", "A")]},
{
- 'style': 'class:selectone.answer',
- 'values': [('a', 'A')],
- 'default': 'default_value',
+ "style": "class:selectone.answer",
+ "values": [("a", "A")],
+ "default": "default_value",
},
),
(
- {'values': [('a', 'A')]},
+ {"values": [("a", "A")]},
{
- 'style': 'class:selectone.answer',
- 'values': [('a', 'A')],
+ "style": "class:selectone.answer",
+ "values": [("a", "A")],
},
),
- ),
+ ],
)
def test_selectone_handler_get_widget_init_kwargs(question, expected):
s = SelectOneHandler(question)
@@ -296,7 +296,7 @@ def test_selectone_handler_get_widget_init_kwargs(question, expected):
def test_selectone_handler_get_keybindings():
- s = SelectOneHandler({'values': [('a', 'A')]})
+ s = SelectOneHandler({"values": [("a", "A")]})
kb = s.get_keybindings()
assert isinstance(kb, KeyBindings)
assert kb.get_bindings_for_keys(Keys.ControlC) is not None
@@ -305,13 +305,13 @@ def test_selectone_handler_get_keybindings():
def test_selectone_handler_get_value(mocker):
s = SelectOneHandler({})
widget_mock = mocker.MagicMock()
- widget_mock.current_value = 'Test text'
+ widget_mock.current_value = "Test text"
s.get_widget = mocker.MagicMock(return_value=widget_mock)
- assert s.get_value() == 'Test text'
+ assert s.get_value() == "Test text"
def test_selectmany_handler_get_layout():
- question = {'values': [('a', 'A')]}
+ question = {"values": [("a", "A")]}
s = SelectManyHandler(question)
layout = s.get_layout()
assert isinstance(layout, HSplit)
@@ -325,7 +325,7 @@ def test_selectmany_handler_get_layout():
def test_selectmany_handler_get_layout_with_msg():
- question = {'message': 'this is a message', 'values': [('a', 'A')]}
+ question = {"message": "this is a message", "values": [("a", "A")]}
s = SelectManyHandler(question)
layout = s.get_layout()
assert isinstance(layout, HSplit)
@@ -336,13 +336,13 @@ def test_selectmany_handler_get_layout_with_msg():
assert layout.children[1].padding == 1
label_ctrl = layout.children[1].children[0]
assert isinstance(label_ctrl, Window)
- assert label_ctrl.content.text() == 'this is a message'
+ assert label_ctrl.content.text() == "this is a message"
input_ctrl = layout.children[1].children[1]
assert isinstance(input_ctrl, Window)
def test_selectmany_handler_get_layout_with_description():
- question = {'description': 'this is a description', 'values': [('a', 'A')]}
+ question = {"description": "this is a description", "values": [("a", "A")]}
s = SelectManyHandler(question)
layout = s.get_layout()
assert isinstance(layout, HSplit)
@@ -350,7 +350,7 @@ def test_selectmany_handler_get_layout_with_description():
assert layout.padding == 1
label_ctrl = layout.children[0]
assert isinstance(label_ctrl, Window)
- assert label_ctrl.content.text[0][1] == 'this is a description'
+ assert label_ctrl.content.text[0][1] == "this is a description"
assert isinstance(layout.children[2], VSplit)
assert len(layout.children[2].children) == 1
@@ -360,28 +360,27 @@ def test_selectmany_handler_get_layout_with_description():
@pytest.mark.parametrize(
- ('question', 'expected'),
- (
+ ("question", "expected"),
+ [
(
{
- 'default': ['a'],
- 'values': [('a', 'A')],
+ "default": ["a"],
+ "values": [("a", "A")],
},
{
- 'default': ['a'],
- 'style': 'class:selectmany.answer',
- 'values': [('a', 'A')],
-
+ "default": ["a"],
+ "style": "class:selectmany.answer",
+ "values": [("a", "A")],
},
),
(
- {'values': [('a', 'A')]},
+ {"values": [("a", "A")]},
{
- 'style': 'class:selectmany.answer',
- 'values': [('a', 'A')],
+ "style": "class:selectmany.answer",
+ "values": [("a", "A")],
},
),
- ),
+ ],
)
def test_selectmany_handler_get_widget_init_kwargs(question, expected):
s = SelectManyHandler(question)
@@ -389,7 +388,7 @@ def test_selectmany_handler_get_widget_init_kwargs(question, expected):
def test_selectmany_handler_get_keybindings():
- s = SelectManyHandler({'values': [('a', 'A')]})
+ s = SelectManyHandler({"values": [("a", "A")]})
kb = s.get_keybindings()
assert isinstance(kb, KeyBindings)
assert kb.get_bindings_for_keys(Keys.ControlC) is not None
@@ -398,13 +397,13 @@ def test_selectmany_handler_get_keybindings():
def test_selectmany_handler_get_value(mocker):
s = SelectManyHandler({})
widget_mock = mocker.MagicMock()
- widget_mock.value = ['a']
+ widget_mock.value = ["a"]
s.get_widget = mocker.MagicMock(return_value=widget_mock)
- assert s.get_value() == ['a']
+ assert s.get_value() == ["a"]
def test_maskedinput_handler_get_layout():
- question = {'mask': '____-____'}
+ question = {"mask": "____-____"}
s = MaskedInputHandler(question)
layout = s.get_layout()
assert isinstance(layout, HSplit)
@@ -418,7 +417,7 @@ def test_maskedinput_handler_get_layout():
def test_maskedinput_handler_get_layout_with_msg():
- question = {'mask': '____-____', 'message': 'this is a message'}
+ question = {"mask": "____-____", "message": "this is a message"}
s = MaskedInputHandler(question)
layout = s.get_layout()
assert isinstance(layout, HSplit)
@@ -429,13 +428,13 @@ def test_maskedinput_handler_get_layout_with_msg():
assert layout.children[0].padding == 1
label_ctrl = layout.children[0].children[0]
assert isinstance(label_ctrl, Window)
- assert label_ctrl.content.text() == 'this is a message'
+ assert label_ctrl.content.text() == "this is a message"
input_ctrl = layout.children[0].children[1]
assert isinstance(input_ctrl, MaskedInput)
def test_maskedinput_handler_get_layout_with_description():
- question = {'mask': '____-____', 'description': 'this is a description'}
+ question = {"mask": "____-____", "description": "this is a description"}
s = MaskedInputHandler(question)
layout = s.get_layout()
assert isinstance(layout, HSplit)
@@ -443,7 +442,7 @@ def test_maskedinput_handler_get_layout_with_description():
assert layout.padding == 1
label_ctrl = layout.children[0]
assert isinstance(label_ctrl, Window)
- assert label_ctrl.content.text[0][1] == 'this is a description'
+ assert label_ctrl.content.text[0][1] == "this is a description"
assert isinstance(layout.children[1], VSplit)
assert len(layout.children[1].children) == 1
@@ -453,26 +452,26 @@ def test_maskedinput_handler_get_layout_with_description():
def test_maskedinput_handler_get_widget_init_kwargs():
- s = MaskedInputHandler({'mask': '____-____'})
+ s = MaskedInputHandler({"mask": "____-____"})
assert s.get_widget_init_kwargs() == {
- 'mask': '____-____',
- 'style': 'class:input.answer',
+ "mask": "____-____",
+ "style": "class:input.answer",
}
def test_maskedinput_handler_get_keybindings():
- s = MaskedInputHandler({'mask': '____-____'})
+ s = MaskedInputHandler({"mask": "____-____"})
kb = s.get_keybindings()
assert isinstance(kb, KeyBindings)
assert kb.get_bindings_for_keys(Keys.ControlC) is not None
def test_maskedinput_handler_get_value(mocker):
- s = MaskedInputHandler({'mask': '____-____'})
+ s = MaskedInputHandler({"mask": "____-____"})
widget_mock = mocker.MagicMock()
- widget_mock.value = 'value'
+ widget_mock.value = "value"
s.get_widget = mocker.MagicMock(return_value=widget_mock)
- assert s.get_value() == 'value'
+ assert s.get_value() == "value"
def test_date_handler_get_layout():
@@ -490,7 +489,7 @@ def test_date_handler_get_layout():
def test_date_handler_get_layout_with_msg():
- question = {'message': 'this is a message'}
+ question = {"message": "this is a message"}
s = DateHandler(question)
layout = s.get_layout()
assert isinstance(layout, HSplit)
@@ -501,13 +500,13 @@ def test_date_handler_get_layout_with_msg():
assert layout.children[0].padding == 1
label_ctrl = layout.children[0].children[0]
assert isinstance(label_ctrl, Window)
- assert label_ctrl.content.text() == 'this is a message'
+ assert label_ctrl.content.text() == "this is a message"
input_ctrl = layout.children[0].children[1]
assert isinstance(input_ctrl, MaskedInput)
def test_date_handler_get_layout_with_description():
- question = {'description': 'this is a description'}
+ question = {"description": "this is a description"}
s = DateHandler(question)
layout = s.get_layout()
assert isinstance(layout, HSplit)
@@ -515,7 +514,7 @@ def test_date_handler_get_layout_with_description():
assert layout.padding == 1
label_ctrl = layout.children[0]
assert isinstance(label_ctrl, Window)
- assert label_ctrl.content.text[0][1] == 'this is a description'
+ assert label_ctrl.content.text[0][1] == "this is a description"
assert isinstance(layout.children[1], VSplit)
assert len(layout.children[1].children) == 1
@@ -527,9 +526,9 @@ def test_date_handler_get_layout_with_description():
def test_date_handler_get_widget_init_kwargs():
s = DateHandler({})
assert s.get_widget_init_kwargs() == {
- 'mask': '____-__-__',
- 'style': 'class:input.answer',
- 'allowed_chars': string.digits,
+ "mask": "____-__-__",
+ "style": "class:input.answer",
+ "allowed_chars": string.digits,
}
@@ -544,9 +543,9 @@ def test_date_handler_get_keybindings():
def test_date_handler_get_value(mocker):
s = DateHandler({})
widget_mock = mocker.MagicMock()
- widget_mock.value = 'value'
+ widget_mock.value = "value"
s.get_widget = mocker.MagicMock(return_value=widget_mock)
- assert s.get_value() == 'value'
+ assert s.get_value() == "value"
def test_daterange_handler_get_layout():
@@ -564,7 +563,7 @@ def test_daterange_handler_get_layout():
def test_daterange_handler_get_layout_with_msg():
- question = {'message': 'this is a message'}
+ question = {"message": "this is a message"}
s = DateRangeHandler(question)
layout = s.get_layout()
assert isinstance(layout, HSplit)
@@ -575,13 +574,13 @@ def test_daterange_handler_get_layout_with_msg():
assert layout.children[0].padding == 1
label_ctrl = layout.children[0].children[0]
assert isinstance(label_ctrl, Window)
- assert label_ctrl.content.text() == 'this is a message'
+ assert label_ctrl.content.text() == "this is a message"
input_ctrl = layout.children[0].children[1]
assert isinstance(input_ctrl, DateRange)
def test_daterange_handler_get_layout_with_description():
- question = {'description': 'this is a description'}
+ question = {"description": "this is a description"}
s = DateRangeHandler(question)
layout = s.get_layout()
assert isinstance(layout, HSplit)
@@ -589,7 +588,7 @@ def test_daterange_handler_get_layout_with_description():
assert layout.padding == 1
label_ctrl = layout.children[0]
assert isinstance(label_ctrl, Window)
- assert label_ctrl.content.text[0][1] == 'this is a description'
+ assert label_ctrl.content.text[0][1] == "this is a description"
assert isinstance(layout.children[1], VSplit)
assert len(layout.children[1].children) == 1
@@ -599,27 +598,26 @@ def test_daterange_handler_get_layout_with_description():
@pytest.mark.parametrize(
- ('question', 'expected'),
- (
+ ("question", "expected"),
+ [
(
{
- 'from_label': 'From',
- 'to_label': 'To',
+ "from_label": "From",
+ "to_label": "To",
},
{
- 'style': 'class:input.answer',
- 'from_label': 'From',
- 'to_label': 'To',
-
+ "style": "class:input.answer",
+ "from_label": "From",
+ "to_label": "To",
},
),
(
{},
{
- 'style': 'class:input.answer',
+ "style": "class:input.answer",
},
),
- ),
+ ],
)
def test_daterange_handler_get_widget_init_kwargs(question, expected):
s = DateRangeHandler(question)
@@ -637,6 +635,6 @@ def test_daterange_handler_get_keybindings():
def test_daterange_handler_get_value(mocker):
s = DateRangeHandler({})
widget_mock = mocker.MagicMock()
- widget_mock.value = 'value'
+ widget_mock.value = "value"
s.get_widget = mocker.MagicMock(return_value=widget_mock)
- assert s.get_value() == 'value'
+ assert s.get_value() == "value"
diff --git a/tests/handlers/test_registry.py b/tests/handlers/test_registry.py
index 100caa7..8e57cab 100644
--- a/tests/handlers/test_registry.py
+++ b/tests/handlers/test_registry.py
@@ -3,7 +3,10 @@
from interrogatio.core.exceptions import AlreadyRegisteredError
from interrogatio.handlers.base import QHandler
from interrogatio.handlers.registry import (
- get_instance, get_registered, QHandlersRegistry, register,
+ QHandlersRegistry,
+ get_instance,
+ get_registered,
+ register,
)
@@ -13,10 +16,10 @@ def test_registry_register():
class TestClass:
pass
- reg.register('alias', TestClass)
+ reg.register("alias", TestClass)
- assert 'alias' in reg
- assert issubclass(reg['alias'], TestClass)
+ assert "alias" in reg
+ assert issubclass(reg["alias"], TestClass)
def test_registry_register_already_registered():
@@ -25,11 +28,11 @@ def test_registry_register_already_registered():
class TestClass:
pass
- reg.register('alias', TestClass)
+ reg.register("alias", TestClass)
with pytest.raises(AlreadyRegisteredError) as cv:
- reg.register('alias', TestClass)
+ reg.register("alias", TestClass)
- assert str(cv.value) == 'alias `alias` already exists.'
+ assert str(cv.value) == "alias `alias` already exists."
def test_registry_get_registered():
@@ -43,13 +46,13 @@ def test_registry_get_registered():
class TestClass:
pass
- reg.register('alias', TestClass)
+ reg.register("alias", TestClass)
registered = reg.get_registered()
assert isinstance(registered, list)
assert len(registered) == 1
- assert registered[0] == 'alias'
+ assert registered[0] == "alias"
def test_registry_get_instance():
@@ -59,9 +62,9 @@ class TestClass:
def __init__(self, question):
self.question = question
- reg.register('test', TestClass)
+ reg.register("test", TestClass)
- question = {'type': 'test'}
+ question = {"type": "test"}
instance = reg.get_instance(question)
@@ -70,27 +73,26 @@ def __init__(self, question):
def test_register(handlers_registry):
-
- @register('alias')
+ @register("alias")
class TestClass(QHandler):
pass
- assert 'alias' in handlers_registry
- assert issubclass(handlers_registry['alias'], TestClass)
+ assert "alias" in handlers_registry
+ assert issubclass(handlers_registry["alias"], TestClass)
def test_register_already_registered(handlers_registry):
-
- @register('alias')
+ @register("alias")
class TestClass(QHandler):
pass
with pytest.raises(AlreadyRegisteredError) as cv:
- @register('alias')
+
+ @register("alias")
class TestClass2(QHandler):
pass
- assert str(cv.value) == 'The handler `alias` is already registered.'
+ assert str(cv.value) == "The handler `alias` is already registered."
def test_get_registered(handlers_registry):
@@ -99,7 +101,7 @@ def test_get_registered(handlers_registry):
assert isinstance(registered, list)
assert len(registered) == 0
- @register('alias')
+ @register("alias")
class TestClass(QHandler):
pass
@@ -107,12 +109,11 @@ class TestClass(QHandler):
assert isinstance(registered, list)
assert len(registered) == 1
- assert registered[0] == 'alias'
+ assert registered[0] == "alias"
def test_get_instance(handlers_registry):
-
- @register('test')
+ @register("test")
class TestClass(QHandler):
def __init__(self, question):
self.question = question
@@ -129,7 +130,7 @@ def get_widget_init_kwargs(self):
def get_widget_class(self):
pass
- question = {'type': 'test'}
+ question = {"type": "test"}
instance = get_instance(question)
diff --git a/tests/shortcuts/test_dialogs.py b/tests/shortcuts/test_dialogs.py
index 0657fd0..70a95f1 100644
--- a/tests/shortcuts/test_dialogs.py
+++ b/tests/shortcuts/test_dialogs.py
@@ -4,178 +4,178 @@
@pytest.mark.parametrize(
- ('func', 'kwargs', 'expected_kwargs'),
- (
+ ("func", "kwargs", "expected_kwargs"),
+ [
(
dialogs.yes_no_dialog,
{
- 'title': 'title',
- 'text': 'text',
- 'yes_text': 'yes_text',
- 'no_text': 'no_text',
+ "title": "title",
+ "text": "text",
+ "yes_text": "yes_text",
+ "no_text": "no_text",
},
{
- 'title': 'title',
- 'text': 'text',
- 'yes_text': 'yes_text',
- 'no_text': 'no_text',
+ "title": "title",
+ "text": "text",
+ "yes_text": "yes_text",
+ "no_text": "no_text",
},
),
(
dialogs.button_dialog,
{
- 'title': 'title',
- 'text': 'text',
+ "title": "title",
+ "text": "text",
},
{
- 'title': 'title',
- 'text': 'text',
- 'buttons': [],
+ "title": "title",
+ "text": "text",
+ "buttons": [],
},
),
(
dialogs.button_dialog,
{
- 'title': 'title',
- 'text': 'text',
- 'buttons': ['btn1', 'btn2'],
+ "title": "title",
+ "text": "text",
+ "buttons": ["btn1", "btn2"],
},
{
- 'title': 'title',
- 'text': 'text',
- 'buttons': ['btn1', 'btn2'],
+ "title": "title",
+ "text": "text",
+ "buttons": ["btn1", "btn2"],
},
),
(
dialogs.input_dialog,
{
- 'title': 'title',
- 'text': 'text',
- 'ok_text': 'ok_text',
- 'cancel_text': 'cancel_text',
+ "title": "title",
+ "text": "text",
+ "ok_text": "ok_text",
+ "cancel_text": "cancel_text",
},
{
- 'title': 'title',
- 'text': 'text',
- 'ok_text': 'ok_text',
- 'cancel_text': 'cancel_text',
- 'completer': None,
- 'password': False,
+ "title": "title",
+ "text": "text",
+ "ok_text": "ok_text",
+ "cancel_text": "cancel_text",
+ "completer": None,
+ "password": False,
},
),
(
dialogs.input_dialog,
{
- 'title': 'title',
- 'text': 'text',
- 'ok_text': 'ok_text',
- 'cancel_text': 'cancel_text',
- 'completer': 'completer',
- 'password': True,
+ "title": "title",
+ "text": "text",
+ "ok_text": "ok_text",
+ "cancel_text": "cancel_text",
+ "completer": "completer",
+ "password": True,
},
{
- 'title': 'title',
- 'text': 'text',
- 'ok_text': 'ok_text',
- 'cancel_text': 'cancel_text',
- 'completer': 'completer',
- 'password': True,
+ "title": "title",
+ "text": "text",
+ "ok_text": "ok_text",
+ "cancel_text": "cancel_text",
+ "completer": "completer",
+ "password": True,
},
),
(
dialogs.message_dialog,
{
- 'title': 'title',
- 'text': 'text',
- 'ok_text': 'ok_text',
+ "title": "title",
+ "text": "text",
+ "ok_text": "ok_text",
},
{
- 'title': 'title',
- 'text': 'text',
- 'ok_text': 'ok_text',
+ "title": "title",
+ "text": "text",
+ "ok_text": "ok_text",
},
),
(
dialogs.radiolist_dialog,
{
- 'title': 'title',
- 'text': 'text',
- 'ok_text': 'ok_text',
- 'cancel_text': 'cancel_text',
+ "title": "title",
+ "text": "text",
+ "ok_text": "ok_text",
+ "cancel_text": "cancel_text",
},
{
- 'title': 'title',
- 'text': 'text',
- 'ok_text': 'ok_text',
- 'cancel_text': 'cancel_text',
- 'values': None,
+ "title": "title",
+ "text": "text",
+ "ok_text": "ok_text",
+ "cancel_text": "cancel_text",
+ "values": None,
},
),
(
dialogs.radiolist_dialog,
{
- 'title': 'title',
- 'text': 'text',
- 'ok_text': 'ok_text',
- 'cancel_text': 'cancel_text',
- 'values': ['a', 'b'],
+ "title": "title",
+ "text": "text",
+ "ok_text": "ok_text",
+ "cancel_text": "cancel_text",
+ "values": ["a", "b"],
},
{
- 'title': 'title',
- 'text': 'text',
- 'ok_text': 'ok_text',
- 'cancel_text': 'cancel_text',
- 'values': ['a', 'b'],
+ "title": "title",
+ "text": "text",
+ "ok_text": "ok_text",
+ "cancel_text": "cancel_text",
+ "values": ["a", "b"],
},
),
(
dialogs.progress_dialog,
{
- 'title': 'title',
- 'text': 'text',
+ "title": "title",
+ "text": "text",
},
{
- 'title': 'title',
- 'text': 'text',
- 'run_callback': None,
+ "title": "title",
+ "text": "text",
+ "run_callback": None,
},
),
(
dialogs.progress_dialog,
{
- 'title': 'title',
- 'text': 'text',
- 'run_callback': 'a function',
+ "title": "title",
+ "text": "text",
+ "run_callback": "a function",
},
{
- 'title': 'title',
- 'text': 'text',
- 'run_callback': 'a function',
+ "title": "title",
+ "text": "text",
+ "run_callback": "a function",
},
),
- ),
+ ],
)
def test_dialogs(mocker, func, kwargs, expected_kwargs):
mocked = mocker.patch(
- f'interrogatio.shortcuts.dialogs.pt_{func.__name__}',
+ f"interrogatio.shortcuts.dialogs.pt_{func.__name__}",
)
mocker.patch(
- 'interrogatio.shortcuts.dialogs.for_dialog',
- return_value='a style',
+ "interrogatio.shortcuts.dialogs.for_dialog",
+ return_value="a style",
)
func(**kwargs)
assert mocked.mock_calls[0].kwargs == {
**expected_kwargs,
- 'style': 'a style',
+ "style": "a style",
}
- kwargs['style'] = 'another style'
+ kwargs["style"] = "another style"
func(**kwargs)
assert mocked.mock_calls[1].kwargs == {
**expected_kwargs,
- 'style': 'another style',
+ "style": "another style",
}
diff --git a/tests/validators/test_builtins.py b/tests/validators/test_builtins.py
index 3656e10..71c4aab 100644
--- a/tests/validators/test_builtins.py
+++ b/tests/validators/test_builtins.py
@@ -20,12 +20,12 @@
@pytest.mark.parametrize(
- 'value',
- (
- '10.0.0.1',
- '192.168.1.1',
- '192.168.1.255',
- ),
+ "value",
+ [
+ "10.0.0.1",
+ "192.168.1.1",
+ "192.168.1.255",
+ ],
)
def test_validate_ipv4_address(value):
v = IPv4Validator()
@@ -33,12 +33,12 @@ def test_validate_ipv4_address(value):
@pytest.mark.parametrize(
- 'value',
- (
- '10.0.0.256',
- '255.255',
- 'a.b.c.d',
- ),
+ "value",
+ [
+ "10.0.0.256",
+ "255.255",
+ "a.b.c.d",
+ ],
)
def test_validate_ipv4_address_invalid(value):
v = IPv4Validator()
@@ -47,17 +47,17 @@ def test_validate_ipv4_address_invalid(value):
@pytest.mark.parametrize(
- 'value',
- (
- 'a',
- 'd sd d',
- ('a',),
- ('a', 'b'),
- ['a'],
+ "value",
+ [
+ "a",
+ "d sd d",
+ ("a",),
+ ("a", "b"),
+ ["a"],
[1, 2, 3],
- {'a': 'v'},
- {'b': 'a', 'a': 'b'},
- ),
+ {"a": "v"},
+ {"b": "a", "a": "b"},
+ ],
)
def test_required_validator(value):
r = RequiredValidator()
@@ -65,15 +65,15 @@ def test_required_validator(value):
@pytest.mark.parametrize(
- 'value',
- (
+ "value",
+ [
None,
False,
- '',
- tuple(),
+ "",
+ (),
[],
{},
- ),
+ ],
)
def test_required_validator_invalid(value):
r = RequiredValidator()
@@ -82,28 +82,28 @@ def test_required_validator_invalid(value):
def test_regex_validator():
- r = RegexValidator(r'^[a-zA-Z]+$')
- assert r.validate('aianaBCBCyasgfdBCbB') is None
+ r = RegexValidator(r"^[a-zA-Z]+$")
+ assert r.validate("aianaBCBCyasgfdBCbB") is None
def test_regex_validator_invalid():
- r = RegexValidator(r'^[a-zA-Z]+$')
+ r = RegexValidator(r"^[a-zA-Z]+$")
with pytest.raises(ValidationError):
- r.validate('aianaBCBCya111')
+ r.validate("aianaBCBCya111")
with pytest.raises(ValidationError):
- r.validate('a##')
+ r.validate("a##")
@pytest.mark.parametrize(
- 'value',
- (
+ "value",
+ [
None,
- '',
- 'gigi@日本語.org',
- 'test@gmail.com',
- 'hello@microsoft.com',
- ),
+ "",
+ "gigi@日本語.org",
+ "test@gmail.com",
+ "hello@microsoft.com",
+ ],
)
def test_email_validator(value):
r = EmailValidator()
@@ -111,12 +111,12 @@ def test_email_validator(value):
@pytest.mark.parametrize(
- 'value',
- (
- '日本語.idn.icann.org',
- 'microsoft.com',
- 'test@domain',
- ),
+ "value",
+ [
+ "日本語.idn.icann.org",
+ "microsoft.com",
+ "test@domain",
+ ],
)
def test_email_validator_invalid(value):
r = EmailValidator()
@@ -125,16 +125,16 @@ def test_email_validator_invalid(value):
@pytest.mark.parametrize(
- 'value',
- (
- 'https://www.日本語.com',
- 'https://gmail.com',
- 'http://test.app.microsoft.com',
- 'https://www.日本語.com:8443',
- 'https://gmail.com:9443',
- 'http://user:pass@test.app.microsoft.com',
- 'ftp://test.local',
- ),
+ "value",
+ [
+ "https://www.日本語.com",
+ "https://gmail.com",
+ "http://test.app.microsoft.com",
+ "https://www.日本語.com:8443",
+ "https://gmail.com:9443",
+ "http://user:pass@test.app.microsoft.com",
+ "ftp://test.local",
+ ],
)
def test_url_validator(value):
r = URLValidator()
@@ -142,12 +142,12 @@ def test_url_validator(value):
@pytest.mark.parametrize(
- 'value',
- (
- 'https://' + 'a' * 254,
- 'https://test',
- 'my.url.com',
- ),
+ "value",
+ [
+ "https://" + "a" * 254,
+ "https://test",
+ "my.url.com",
+ ],
)
def test_url_validator_invalid(value):
r = URLValidator()
@@ -156,15 +156,15 @@ def test_url_validator_invalid(value):
@pytest.mark.parametrize(
- 'value',
- (
- '',
+ "value",
+ [
+ "",
[],
- 'a' * 99,
- 'b' * 100,
- ['x' for _ in range(99)],
- ['x' for _ in range(100)],
- ),
+ "a" * 99,
+ "b" * 100,
+ ["x" for _ in range(99)],
+ ["x" for _ in range(100)],
+ ],
)
def test_maxlength_validator(value):
r = MaxLengthValidator(100)
@@ -172,14 +172,14 @@ def test_maxlength_validator(value):
@pytest.mark.parametrize(
- 'value',
- (
- 'a' * 99,
- 'b' * 100,
- ['x' for _ in range(99)],
- ['x' for _ in range(100)],
+ "value",
+ [
+ "a" * 99,
+ "b" * 100,
+ ["x" for _ in range(99)],
+ ["x" for _ in range(100)],
66,
- ),
+ ],
)
def test_maxlength_validator_invalid(value):
r = MaxLengthValidator(98)
@@ -188,15 +188,15 @@ def test_maxlength_validator_invalid(value):
@pytest.mark.parametrize(
- 'value',
- (
- '0' * 98,
- 'a' * 99,
- 'b' * 100,
- ['x' for _ in range(98)],
- ['x' for _ in range(99)],
- ['x' for _ in range(100)],
- ),
+ "value",
+ [
+ "0" * 98,
+ "a" * 99,
+ "b" * 100,
+ ["x" for _ in range(98)],
+ ["x" for _ in range(99)],
+ ["x" for _ in range(100)],
+ ],
)
def test_minlength_validator(value):
r = MinLengthValidator(98)
@@ -204,14 +204,14 @@ def test_minlength_validator(value):
@pytest.mark.parametrize(
- 'value',
- (
- 'a' * 99,
- 'b' * 100,
- ['x' for _ in range(99)],
- ['x' for _ in range(100)],
+ "value",
+ [
+ "a" * 99,
+ "b" * 100,
+ ["x" for _ in range(99)],
+ ["x" for _ in range(100)],
25,
- ),
+ ],
)
def test_minlength_validator_invalid(value):
r = MinLengthValidator(101)
@@ -220,8 +220,8 @@ def test_minlength_validator_invalid(value):
@pytest.mark.parametrize(
- 'value',
- (-1, 0, 1, 20.93, -11.2994, 0xff12, 0o7146, 0b11010011),
+ "value",
+ [-1, 0, 1, 20.93, -11.2994, 0xFF12, 0o7146, 0b11010011],
)
def test_number_validator(value):
r = NumberValidator()
@@ -229,8 +229,8 @@ def test_number_validator(value):
@pytest.mark.parametrize(
- 'value',
- ('', 'string', list(), list([1, 2, 3]), dict()),
+ "value",
+ ["", "string", [], [1, 2, 3], {}],
)
def test_number_validator_invalid(value):
r = NumberValidator()
@@ -239,8 +239,8 @@ def test_number_validator_invalid(value):
@pytest.mark.parametrize(
- 'value',
- (-1, 0, 1, 0xff12, 0o7146, 0b11010011),
+ "value",
+ [-1, 0, 1, 0xFF12, 0o7146, 0b11010011],
)
def test_integer_validator(value):
r = IntegerValidator()
@@ -248,8 +248,8 @@ def test_integer_validator(value):
@pytest.mark.parametrize(
- 'value',
- ('-1', '0', '1', 20.93, -11.2994, [1, 2, 3]),
+ "value",
+ ["-1", "0", "1", 20.93, -11.2994, [1, 2, 3]],
)
def test_integer_validator_invalid(value):
r = IntegerValidator()
@@ -258,8 +258,8 @@ def test_integer_validator_invalid(value):
@pytest.mark.parametrize(
- 'value',
- (-1, 0, 1, 3.88, 0o10, 0b1000, 0x0F),
+ "value",
+ [-1, 0, 1, 3.88, 0o10, 0x0F],
)
def test_min_validator(value):
r = MinValidator(-2)
@@ -267,8 +267,8 @@ def test_min_validator(value):
@pytest.mark.parametrize(
- 'value',
- (-3.88, -0o10, -0b1000, -0x0F, [1, 2, 3]),
+ "value",
+ [-3.88, -0o10, -0x0F, [1, 2, 3]],
)
def test_min_validator_invalid(value):
r = MinValidator(-2)
@@ -277,8 +277,8 @@ def test_min_validator_invalid(value):
@pytest.mark.parametrize(
- 'value',
- (-1, 0, 1, 3.88, 0o10, 0b1000, 0x0F),
+ "value",
+ [-1, 0, 1, 3.88, 0o10, 0x0F],
)
def test_max_validator(value):
r = MaxValidator(16)
@@ -286,8 +286,8 @@ def test_max_validator(value):
@pytest.mark.parametrize(
- 'value',
- (-1, 0, 1, 3.88, 0o10, 0b1000, 0x0F, [1, 2, 3]),
+ "value",
+ [-1, 0, 1, 3.88, 0o10, 0x0F, [1, 2, 3]],
)
def test_max_validator_invalid(value):
r = MaxValidator(-2)
@@ -296,8 +296,8 @@ def test_max_validator_invalid(value):
@pytest.mark.parametrize(
- 'value',
- (-1, 0, 1, 3.88, 0o10, 0b1000, 0x0F),
+ "value",
+ [-1, 0, 1, 3.88, 0o10, 0x0F],
)
def test_range_validator(value):
r = RangeValidator(-2, 16)
@@ -305,8 +305,8 @@ def test_range_validator(value):
@pytest.mark.parametrize(
- 'value',
- (-1, 0, 1, 3.88, 0o10, 0b1000, 0x0F, [1, 2, 3]),
+ "value",
+ [-1, 0, 1, 3.88, 0o10, 0x0F, [1, 2, 3]],
)
def test_range_validator_invalid(value):
r = RangeValidator(-20, -2)
@@ -315,13 +315,13 @@ def test_range_validator_invalid(value):
@pytest.mark.parametrize(
- 'value',
- (
- '2020-01-01T12:00:00',
- '2020-02-29T23:00:00',
- '',
+ "value",
+ [
+ "2020-01-01T12:00:00",
+ "2020-02-29T23:00:00",
+ "",
None,
- ),
+ ],
)
def test_date_validator(value):
r = DateTimeValidator()
@@ -329,8 +329,8 @@ def test_date_validator(value):
@pytest.mark.parametrize(
- 'value',
- (-1, 0, 1, 3.88, 0o10, 0b1000, 0x0F, [1, 2, 3], '2020-02-30T23:00:00'),
+ "value",
+ [-1, 0, 1, 3.88, 0o10, 0x0F, [1, 2, 3], "2020-02-30T23:00:00"],
)
def test_date_validator_invalid(value):
r = DateTimeValidator()
@@ -339,29 +339,29 @@ def test_date_validator_invalid(value):
@pytest.mark.parametrize(
- 'value',
- (
- {'from': '2020-01-01T12:00:00', 'to': '2020-03-01T12:00:00'},
- {'from': '2020-01-01T12:00:00', 'to': ''},
- {'from': None, 'to': '2020-03-01T12:00:00'},
- '',
+ "value",
+ [
+ {"from": "2020-01-01T12:00:00", "to": "2020-03-01T12:00:00"},
+ {"from": "2020-01-01T12:00:00", "to": ""},
+ {"from": None, "to": "2020-03-01T12:00:00"},
+ "",
None,
- ),
+ ],
)
def test_daterange_validator(value):
- r = DateTimeRangeValidator(format_pattern='%Y-%m-%dT%H:%M:%S')
+ r = DateTimeRangeValidator(format_pattern="%Y-%m-%dT%H:%M:%S")
assert r.validate(value) is None
@pytest.mark.parametrize(
- 'value',
- (
- {'from': '2020-01-01T12:00:00', 'to': '2019-03-01T12:00:00'},
- {'from': 'xxxx', 'to': 'xxxx'},
+ "value",
+ [
+ {"from": "2020-01-01T12:00:00", "to": "2019-03-01T12:00:00"},
+ {"from": "xxxx", "to": "xxxx"},
[1, 2, 3],
- ),
+ ],
)
def test_daterange_validator_invalid(value):
- r = DateTimeRangeValidator(format_pattern='%Y-%m-%dT%H:%M:%S')
+ r = DateTimeRangeValidator(format_pattern="%Y-%m-%dT%H:%M:%S")
with pytest.raises(ValidationError):
r.validate(value)
diff --git a/tests/validators/test_registry.py b/tests/validators/test_registry.py
index 44c08b1..6123c6a 100644
--- a/tests/validators/test_registry.py
+++ b/tests/validators/test_registry.py
@@ -3,10 +3,10 @@
from interrogatio.core.exceptions import AlreadyRegisteredError
from interrogatio.validators.base import Validator
from interrogatio.validators.registry import (
+ ValidatorsRegistry,
get_instance,
get_registered,
register,
- ValidatorsRegistry,
)
@@ -16,10 +16,10 @@ def test_registry_register():
class TestClass:
pass
- reg.register('alias', TestClass)
+ reg.register("alias", TestClass)
- assert 'alias' in reg
- assert issubclass(reg['alias'], TestClass)
+ assert "alias" in reg
+ assert issubclass(reg["alias"], TestClass)
def test_registry_register_already_registered():
@@ -28,11 +28,11 @@ def test_registry_register_already_registered():
class TestClass:
pass
- reg.register('alias', TestClass)
+ reg.register("alias", TestClass)
with pytest.raises(AlreadyRegisteredError) as cv:
- reg.register('alias', TestClass)
+ reg.register("alias", TestClass)
- assert str(cv.value) == 'validator `alias` already exists.'
+ assert str(cv.value) == "validator `alias` already exists."
def test_registry_get_registered():
@@ -46,13 +46,13 @@ def test_registry_get_registered():
class TestClass:
pass
- reg.register('alias', TestClass)
+ reg.register("alias", TestClass)
registered = reg.get_registered()
assert isinstance(registered, list)
assert len(registered) == 1
- assert registered[0] == 'alias'
+ assert registered[0] == "alias"
def test_registry_get_instance():
@@ -65,9 +65,9 @@ def __init__(self, message=None):
def validate(self, value):
pass
- reg.register('test', TestClass)
+ reg.register("test", TestClass)
- validator = {'name': 'test'}
+ validator = {"name": "test"}
instance = reg.get_instance(validator)
@@ -75,30 +75,29 @@ def validate(self, value):
def test_register(validators_registry):
-
- @register('alias')
+ @register("alias")
class TestClass(Validator):
def validate(self, value):
pass
- assert 'alias' in validators_registry
- assert issubclass(validators_registry['alias'], TestClass)
+ assert "alias" in validators_registry
+ assert issubclass(validators_registry["alias"], TestClass)
def test_register_already_registered(validators_registry):
-
- @register('alias')
+ @register("alias")
class TestClass(Validator):
def validate(self, value):
pass
with pytest.raises(AlreadyRegisteredError) as cv:
- @register('alias')
+
+ @register("alias")
class TestClass2(Validator):
def validate(self, value):
pass
- assert str(cv.value) == 'The validator `alias` is already registered.'
+ assert str(cv.value) == "The validator `alias` is already registered."
def test_get_registered(validators_registry):
@@ -107,7 +106,7 @@ def test_get_registered(validators_registry):
assert isinstance(registered, list)
assert len(registered) == 0
- @register('alias')
+ @register("alias")
class TestClass(Validator):
def validate(self, value):
pass
@@ -116,13 +115,12 @@ def validate(self, value):
assert isinstance(registered, list)
assert len(registered) == 1
- assert registered[0] == 'alias'
+ assert registered[0] == "alias"
-@pytest.mark.parametrize('args', ({}, {'message': 'message'}))
+@pytest.mark.parametrize("args", [{}, {"message": "message"}])
def test_get_instance(validators_registry, args):
-
- @register('test')
+ @register("test")
class TestClass(Validator):
def __init__(self, message=None):
self.message = message
@@ -130,7 +128,7 @@ def __init__(self, message=None):
def validate(self, value):
pass
- validator = {'name': 'test', 'args': args}
+ validator = {"name": "test", "args": args}
instance = get_instance(validator)
assert isinstance(instance, TestClass)
diff --git a/tests/widgets/test_wizard.py b/tests/widgets/test_wizard.py
index 3b6a5d0..e74aeb5 100644
--- a/tests/widgets/test_wizard.py
+++ b/tests/widgets/test_wizard.py
@@ -1,4 +1,4 @@
-from interrogatio.handlers import get_instance, QHandler
+from interrogatio.handlers import QHandler, get_instance
from interrogatio.validators import RequiredValidator
from interrogatio.widgets.wizard import WizardDialog
@@ -6,160 +6,160 @@
def test_wizard_init_default():
questions = [
{
- 'name': 'question1',
- 'type': 'input',
- 'message': 'message',
- 'description': 'description',
- 'validators': [{'name': 'required'}],
+ "name": "question1",
+ "type": "input",
+ "message": "message",
+ "description": "description",
+ "validators": [{"name": "required"}],
},
{
- 'name': 'question2',
- 'type': 'input',
- 'message': 'message',
- 'description': 'description',
- 'validators': [{'name': 'required'}],
- 'disabled': True,
+ "name": "question2",
+ "type": "input",
+ "message": "message",
+ "description": "description",
+ "validators": [{"name": "required"}],
+ "disabled": True,
},
{
- 'name': 'question3',
- 'type': 'input',
- 'message': 'message',
- 'description': 'description',
- 'validators': [{'name': 'required'}],
+ "name": "question3",
+ "type": "input",
+ "message": "message",
+ "description": "description",
+ "validators": [{"name": "required"}],
},
]
handlers = [get_instance(q) for q in questions]
- wz = WizardDialog('title', handlers)
+ wz = WizardDialog("title", handlers)
assert len(wz.steps) == 3
def test_wizard_init_intro_summary():
questions = [
{
- 'name': 'question1',
- 'type': 'input',
- 'message': 'message',
- 'description': 'description',
- 'validators': [{'name': 'required'}],
+ "name": "question1",
+ "type": "input",
+ "message": "message",
+ "description": "description",
+ "validators": [{"name": "required"}],
},
{
- 'name': 'question2',
- 'type': 'input',
- 'message': 'message',
- 'description': 'description',
- 'validators': [{'name': 'required'}],
+ "name": "question2",
+ "type": "input",
+ "message": "message",
+ "description": "description",
+ "validators": [{"name": "required"}],
},
]
handlers = [get_instance(q) for q in questions]
- wz = WizardDialog('title', handlers, intro='intro', summary=True)
+ wz = WizardDialog("title", handlers, intro="intro", summary=True)
assert len(wz.steps) == 4
def test_wizard_get_title():
questions = [
{
- 'name': 'question1',
- 'type': 'input',
- 'message': 'message',
- 'description': 'description',
- 'validators': [{'name': 'required'}],
+ "name": "question1",
+ "type": "input",
+ "message": "message",
+ "description": "description",
+ "validators": [{"name": "required"}],
},
{
- 'name': 'question2',
- 'type': 'input',
- 'message': 'message',
- 'description': 'description',
- 'validators': [{'name': 'required'}],
+ "name": "question2",
+ "type": "input",
+ "message": "message",
+ "description": "description",
+ "validators": [{"name": "required"}],
},
]
handlers = [get_instance(q) for q in questions]
- wz = WizardDialog('title', handlers)
- assert wz.get_title() == 'title - 1 of 2'
+ wz = WizardDialog("title", handlers)
+ assert wz.get_title() == "title - 1 of 2"
def test_wizard_get_steps_label():
questions = [
{
- 'name': 'question1',
- 'type': 'input',
- 'message': 'message',
- 'description': 'description',
- 'validators': [{'name': 'required'}],
+ "name": "question1",
+ "type": "input",
+ "message": "message",
+ "description": "description",
+ "validators": [{"name": "required"}],
},
{
- 'name': 'question2',
- 'type': 'input',
- 'message': 'message',
- 'description': 'description',
- 'validators': [{'name': 'required'}],
+ "name": "question2",
+ "type": "input",
+ "message": "message",
+ "description": "description",
+ "validators": [{"name": "required"}],
},
{
- 'name': 'question3',
- 'type': 'input',
- 'message': 'message',
- 'description': 'description',
- 'disabled': True,
+ "name": "question3",
+ "type": "input",
+ "message": "message",
+ "description": "description",
+ "disabled": True,
},
]
handlers = [get_instance(q) for q in questions]
- wz = WizardDialog('title', handlers)
+ wz = WizardDialog("title", handlers)
steps_lables = wz.get_steps_labels()
class_current = steps_lables.children[0].content.text[0][0]
- assert 'class:dialog.step.current ' == class_current
- assert '1. Question1' == steps_lables.children[0].content.text[0][1]
- assert 'class:dialog.step ' == steps_lables.children[1].content.text[0][0]
- assert '2. Question2' == steps_lables.children[1].content.text[0][1]
- assert 'disabled' in steps_lables.children[2].content.text[0][0]
- assert '3. Question3' == steps_lables.children[2].content.text[0][1]
+ assert "class:dialog.step.current " == class_current
+ assert "1. Question1" == steps_lables.children[0].content.text[0][1]
+ assert "class:dialog.step " == steps_lables.children[1].content.text[0][0]
+ assert "2. Question2" == steps_lables.children[1].content.text[0][1]
+ assert "disabled" in steps_lables.children[2].content.text[0][0]
+ assert "3. Question3" == steps_lables.children[2].content.text[0][1]
def test_wizard_get_status():
questions = [
{
- 'name': 'question1',
- 'type': 'input',
- 'message': 'message',
- 'description': 'description',
- 'validators': [{'name': 'required'}],
+ "name": "question1",
+ "type": "input",
+ "message": "message",
+ "description": "description",
+ "validators": [{"name": "required"}],
},
{
- 'name': 'question2',
- 'type': 'input',
- 'message': 'message',
- 'description': 'description',
- 'validators': [{'name': 'required'}],
+ "name": "question2",
+ "type": "input",
+ "message": "message",
+ "description": "description",
+ "validators": [{"name": "required"}],
},
]
handlers = [get_instance(q) for q in questions]
- wz = WizardDialog('title', handlers)
- assert wz.get_status().text == ''
+ wz = WizardDialog("title", handlers)
+ assert wz.get_status().text == ""
- wz.error_messages = 'An error'
- assert wz.get_status().content.text[0][0] == 'class:error'
- assert wz.get_status().content.text[0][1] == 'An error'
+ wz.error_messages = "An error"
+ assert wz.get_status().content.text[0][0] == "class:error"
+ assert wz.get_status().content.text[0][1] == "An error"
def test_wizard_cancel(mocker):
mocked_app = mocker.MagicMock()
- mocker.patch('interrogatio.widgets.wizard.get_app', return_value=mocked_app)
+ mocker.patch("interrogatio.widgets.wizard.get_app", return_value=mocked_app)
questions = [
{
- 'name': 'question1',
- 'type': 'input',
- 'message': 'message',
- 'description': 'description',
- 'validators': [{'name': 'required'}],
+ "name": "question1",
+ "type": "input",
+ "message": "message",
+ "description": "description",
+ "validators": [{"name": "required"}],
},
{
- 'name': 'question2',
- 'type': 'input',
- 'message': 'message',
- 'description': 'description',
- 'validators': [{'name': 'required'}],
+ "name": "question2",
+ "type": "input",
+ "message": "message",
+ "description": "description",
+ "validators": [{"name": "required"}],
},
]
handlers = [get_instance(q) for q in questions]
- wz = WizardDialog('title', handlers)
+ wz = WizardDialog("title", handlers)
wz.cancel()
mocked_app.exit.assert_called_once_with(result=False)
@@ -169,35 +169,35 @@ def always_true(context):
return True
mocked_app = mocker.MagicMock()
- mocker.patch('interrogatio.widgets.wizard.get_app', return_value=mocked_app)
+ mocker.patch("interrogatio.widgets.wizard.get_app", return_value=mocked_app)
questions = [
{
- 'name': 'question1',
- 'type': 'input',
- 'message': 'message',
- 'description': 'description',
- 'validators': [{'name': 'required'}],
+ "name": "question1",
+ "type": "input",
+ "message": "message",
+ "description": "description",
+ "validators": [{"name": "required"}],
},
{
- 'name': 'question2',
- 'type': 'input',
- 'message': 'message',
- 'description': 'description',
- 'validators': [{'name': 'required'}],
- 'disabled': always_true,
+ "name": "question2",
+ "type": "input",
+ "message": "message",
+ "description": "description",
+ "validators": [{"name": "required"}],
+ "disabled": always_true,
},
{
- 'name': 'question3',
- 'type': 'input',
- 'message': 'message',
- 'description': 'description',
- 'validators': [{'name': 'required'}],
- 'disabled': False,
+ "name": "question3",
+ "type": "input",
+ "message": "message",
+ "description": "description",
+ "validators": [{"name": "required"}],
+ "disabled": False,
},
]
handlers = [get_instance(q) for q in questions]
- mocked_validate = mocker.patch.object(WizardDialog, 'validate')
- wz = WizardDialog('title', handlers)
+ mocked_validate = mocker.patch.object(WizardDialog, "validate")
+ wz = WizardDialog("title", handlers)
wz.next() # noqa: B305
assert wz.current_step_idx == 2
assert wz.current_step == wz.steps[2]
@@ -209,34 +209,34 @@ def always_true(context):
def test_wizard_next_with_disabled(mocker):
mocked_app = mocker.MagicMock()
- mocker.patch('interrogatio.widgets.wizard.get_app', return_value=mocked_app)
+ mocker.patch("interrogatio.widgets.wizard.get_app", return_value=mocked_app)
questions = [
{
- 'name': 'question1',
- 'type': 'input',
- 'message': 'message',
- 'description': 'description',
- 'validators': [{'name': 'required'}],
+ "name": "question1",
+ "type": "input",
+ "message": "message",
+ "description": "description",
+ "validators": [{"name": "required"}],
},
{
- 'name': 'question2',
- 'type': 'input',
- 'message': 'message',
- 'description': 'description',
- 'validators': [{'name': 'required'}],
+ "name": "question2",
+ "type": "input",
+ "message": "message",
+ "description": "description",
+ "validators": [{"name": "required"}],
},
{
- 'name': 'question3',
- 'type': 'input',
- 'message': 'message',
- 'description': 'description',
- 'validators': [{'name': 'required'}],
- 'disabled': True,
+ "name": "question3",
+ "type": "input",
+ "message": "message",
+ "description": "description",
+ "validators": [{"name": "required"}],
+ "disabled": True,
},
]
handlers = [get_instance(q) for q in questions]
- mocked_validate = mocker.patch.object(WizardDialog, 'validate')
- wz = WizardDialog('title', handlers)
+ mocked_validate = mocker.patch.object(WizardDialog, "validate")
+ wz = WizardDialog("title", handlers)
wz.next() # noqa: B305
assert wz.current_step_idx == 1
assert wz.current_step == wz.steps[1]
@@ -248,41 +248,41 @@ def test_wizard_next_with_disabled(mocker):
def test_wizard_previous(mocker):
mocked_app = mocker.MagicMock()
- mocker.patch('interrogatio.widgets.wizard.get_app', return_value=mocked_app)
+ mocker.patch("interrogatio.widgets.wizard.get_app", return_value=mocked_app)
questions = [
{
- 'name': 'question1',
- 'type': 'input',
- 'message': 'message',
- 'description': 'description',
- 'validators': [{'name': 'required'}],
+ "name": "question1",
+ "type": "input",
+ "message": "message",
+ "description": "description",
+ "validators": [{"name": "required"}],
},
{
- 'name': 'question2',
- 'type': 'input',
- 'message': 'message',
- 'description': 'description',
- 'validators': [{'name': 'required'}],
- 'disabled': True,
+ "name": "question2",
+ "type": "input",
+ "message": "message",
+ "description": "description",
+ "validators": [{"name": "required"}],
+ "disabled": True,
},
{
- 'name': 'question3',
- 'type': 'input',
- 'message': 'message',
- 'description': 'description',
- 'validators': [{'name': 'required'}],
+ "name": "question3",
+ "type": "input",
+ "message": "message",
+ "description": "description",
+ "validators": [{"name": "required"}],
},
{
- 'name': 'question4',
- 'type': 'input',
- 'message': 'message',
- 'description': 'description',
- 'validators': [{'name': 'required'}],
+ "name": "question4",
+ "type": "input",
+ "message": "message",
+ "description": "description",
+ "validators": [{"name": "required"}],
},
]
handlers = [get_instance(q) for q in questions]
- mocker.patch.object(WizardDialog, 'validate')
- wz = WizardDialog('title', handlers)
+ mocker.patch.object(WizardDialog, "validate")
+ wz = WizardDialog("title", handlers)
wz.next() # noqa: B305
wz.previous()
assert wz.current_step_idx == 0
@@ -293,26 +293,26 @@ def test_wizard_previous(mocker):
def test_wizard_next_latest_step(mocker):
mocked_app = mocker.MagicMock()
- mocker.patch('interrogatio.widgets.wizard.get_app', return_value=mocked_app)
+ mocker.patch("interrogatio.widgets.wizard.get_app", return_value=mocked_app)
questions = [
{
- 'name': 'question1',
- 'type': 'input',
- 'message': 'message',
- 'description': 'description',
- 'validators': [{'name': 'required'}],
+ "name": "question1",
+ "type": "input",
+ "message": "message",
+ "description": "description",
+ "validators": [{"name": "required"}],
},
{
- 'name': 'question2',
- 'type': 'input',
- 'message': 'message',
- 'description': 'description',
- 'validators': [{'name': 'required'}],
+ "name": "question2",
+ "type": "input",
+ "message": "message",
+ "description": "description",
+ "validators": [{"name": "required"}],
},
]
handlers = [get_instance(q) for q in questions]
- mocked_validate = mocker.patch.object(WizardDialog, 'validate')
- wz = WizardDialog('title', handlers)
+ mocked_validate = mocker.patch.object(WizardDialog, "validate")
+ wz = WizardDialog("title", handlers)
wz.next() # noqa: B305
wz.next() # noqa: B305
assert wz.current_step_idx == 1
@@ -325,26 +325,26 @@ def test_wizard_next_latest_step(mocker):
def test_wizard_previous_first_step(mocker):
mocked_app = mocker.MagicMock()
- mocker.patch('interrogatio.widgets.wizard.get_app', return_value=mocked_app)
+ mocker.patch("interrogatio.widgets.wizard.get_app", return_value=mocked_app)
questions = [
{
- 'name': 'question1',
- 'type': 'input',
- 'message': 'message',
- 'description': 'description',
- 'validators': [{'name': 'required'}],
+ "name": "question1",
+ "type": "input",
+ "message": "message",
+ "description": "description",
+ "validators": [{"name": "required"}],
},
{
- 'name': 'question2',
- 'type': 'input',
- 'message': 'message',
- 'description': 'description',
- 'validators': [{'name': 'required'}],
+ "name": "question2",
+ "type": "input",
+ "message": "message",
+ "description": "description",
+ "validators": [{"name": "required"}],
},
]
handlers = [get_instance(q) for q in questions]
- mocker.patch.object(WizardDialog, 'validate')
- wz = WizardDialog('title', handlers)
+ mocker.patch.object(WizardDialog, "validate")
+ wz = WizardDialog("title", handlers)
wz.next() # noqa: B305
wz.previous()
wz.previous()
@@ -356,26 +356,26 @@ def test_wizard_previous_first_step(mocker):
def test_wizard_next_latest_step_with_summary(mocker):
mocked_app = mocker.MagicMock()
- mocker.patch('interrogatio.widgets.wizard.get_app', return_value=mocked_app)
+ mocker.patch("interrogatio.widgets.wizard.get_app", return_value=mocked_app)
questions = [
{
- 'name': 'question1',
- 'type': 'input',
- 'message': 'message',
- 'description': 'description',
- 'validators': [{'name': 'required'}],
+ "name": "question1",
+ "type": "input",
+ "message": "message",
+ "description": "description",
+ "validators": [{"name": "required"}],
},
{
- 'name': 'question2',
- 'type': 'input',
- 'message': 'message',
- 'description': 'description',
- 'validators': [{'name': 'required'}],
+ "name": "question2",
+ "type": "input",
+ "message": "message",
+ "description": "description",
+ "validators": [{"name": "required"}],
},
]
handlers = [get_instance(q) for q in questions]
- mocked_validate = mocker.patch.object(WizardDialog, 'validate')
- wz = WizardDialog('title', handlers, summary=True)
+ mocked_validate = mocker.patch.object(WizardDialog, "validate")
+ wz = WizardDialog("title", handlers, summary=True)
wz.next() # noqa: B305
wz.next() # noqa: B305
wz.next() # noqa: B305
@@ -389,49 +389,51 @@ def test_wizard_next_latest_step_with_summary(mocker):
def test_get_summary(mocker):
mocked_app = mocker.MagicMock()
- mocker.patch('interrogatio.widgets.wizard.get_app', return_value=mocked_app)
+ mocker.patch("interrogatio.widgets.wizard.get_app", return_value=mocked_app)
questions = [
{
- 'name': 'question1',
- 'type': 'input',
- 'message': 'message',
- 'description': 'description',
- 'validators': [{'name': 'required'}],
+ "name": "question1",
+ "type": "input",
+ "message": "message",
+ "description": "description",
+ "validators": [{"name": "required"}],
},
{
- 'name': 'question2',
- 'type': 'input',
- 'message': 'message',
- 'description': 'description',
- 'validators': [{'name': 'required'}],
+ "name": "question2",
+ "type": "input",
+ "message": "message",
+ "description": "description",
+ "validators": [{"name": "required"}],
},
]
handlers = [get_instance(q) for q in questions]
mocker.patch.object(
- QHandler, 'get_formatted_value', side_effect=['value1', 'value2'],
+ QHandler,
+ "get_formatted_value",
+ side_effect=["value1", "value2"],
)
- wz = WizardDialog('title', handlers, summary=True)
+ wz = WizardDialog("title", handlers, summary=True)
summary = wz.get_summary()
expected_text1 = summary.content.text[0][1] + summary.content.text[1][1]
expected_text2 = summary.content.text[2][1] + summary.content.text[3][1]
- assert 'Question1: value1' in expected_text1
- assert 'Question2: value2' in expected_text2
+ assert "Question1: value1" in expected_text1
+ assert "Question2: value2" in expected_text2
def test_single_step(mocker):
mocked_app = mocker.MagicMock()
- mocker.patch('interrogatio.widgets.wizard.get_app', return_value=mocked_app)
+ mocker.patch("interrogatio.widgets.wizard.get_app", return_value=mocked_app)
questions = [
{
- 'name': 'question1',
- 'type': 'input',
- 'message': 'message',
- 'description': 'description',
+ "name": "question1",
+ "type": "input",
+ "message": "message",
+ "description": "description",
},
]
handlers = [get_instance(q) for q in questions]
- wz = WizardDialog('title', handlers)
+ wz = WizardDialog("title", handlers)
wz.next() # noqa: B305
assert wz.current_step_idx == 0
assert wz.current_step == wz.steps[0]
@@ -442,127 +444,127 @@ def test_single_step(mocker):
def test_wizard_next_validate_invalid(mocker):
mocked_app = mocker.MagicMock()
- mocker.patch('interrogatio.widgets.wizard.get_app', return_value=mocked_app)
+ mocker.patch("interrogatio.widgets.wizard.get_app", return_value=mocked_app)
questions = [
{
- 'name': 'question1',
- 'type': 'input',
- 'message': 'message',
- 'description': 'description',
- 'validators': [RequiredValidator('This field is required')],
+ "name": "question1",
+ "type": "input",
+ "message": "message",
+ "description": "description",
+ "validators": [RequiredValidator("This field is required")],
},
]
handlers = [get_instance(q) for q in questions]
- wz = WizardDialog('title', handlers)
+ wz = WizardDialog("title", handlers)
wz.next() # noqa: B305
assert wz.current_step_idx == 0
assert wz.current_step == wz.steps[0]
assert len(wz.buttons) == 2
- assert wz.error_messages == 'This field is required'
+ assert wz.error_messages == "This field is required"
def test_wizard_get_current_step_container(mocker):
mocked_app = mocker.MagicMock()
- mocker.patch('interrogatio.widgets.wizard.get_app', return_value=mocked_app)
+ mocker.patch("interrogatio.widgets.wizard.get_app", return_value=mocked_app)
questions = [
{
- 'name': 'question1',
- 'type': 'input',
- 'message': 'message',
- 'description': 'description',
+ "name": "question1",
+ "type": "input",
+ "message": "message",
+ "description": "description",
},
]
handlers = [get_instance(q) for q in questions]
- wz = WizardDialog('title', handlers)
- assert wz.get_current_step_container() == wz.steps[0]['layout']
+ wz = WizardDialog("title", handlers)
+ assert wz.get_current_step_container() == wz.steps[0]["layout"]
def test_wizard_get_buttons_container(mocker):
mocked_app = mocker.MagicMock()
- mocker.patch('interrogatio.widgets.wizard.get_app', return_value=mocked_app)
+ mocker.patch("interrogatio.widgets.wizard.get_app", return_value=mocked_app)
questions = [
{
- 'name': 'question1',
- 'type': 'input',
- 'message': 'message',
- 'description': 'description',
+ "name": "question1",
+ "type": "input",
+ "message": "message",
+ "description": "description",
},
]
handlers = [get_instance(q) for q in questions]
- wz = WizardDialog('title', handlers)
+ wz = WizardDialog("title", handlers)
assert wz.get_buttons_container() is not None
def test_wizard_fast_forward(mocker):
mocked_app = mocker.MagicMock()
- mocker.patch('interrogatio.widgets.wizard.get_app', return_value=mocked_app)
+ mocker.patch("interrogatio.widgets.wizard.get_app", return_value=mocked_app)
questions = [
{
- 'name': 'question1',
- 'type': 'input',
- 'message': 'message',
- 'description': 'description',
- 'default': 'value',
- 'validators': [{'name': 'required'}],
+ "name": "question1",
+ "type": "input",
+ "message": "message",
+ "description": "description",
+ "default": "value",
+ "validators": [{"name": "required"}],
},
{
- 'name': 'question2',
- 'type': 'input',
- 'message': 'message',
- 'description': 'description',
- 'validators': [{'name': 'required'}],
- 'disabled': True,
+ "name": "question2",
+ "type": "input",
+ "message": "message",
+ "description": "description",
+ "validators": [{"name": "required"}],
+ "disabled": True,
},
{
- 'name': 'question3',
- 'type': 'input',
- 'message': 'message',
- 'description': 'description',
- 'default': 'value',
- 'validators': [{'name': 'required'}],
+ "name": "question3",
+ "type": "input",
+ "message": "message",
+ "description": "description",
+ "default": "value",
+ "validators": [{"name": "required"}],
},
]
handlers = [get_instance(q) for q in questions]
- mocker.patch.object(WizardDialog, 'validate')
- wz = WizardDialog('title', handlers, fast_forward=True)
+ mocker.patch.object(WizardDialog, "validate")
+ wz = WizardDialog("title", handlers, fast_forward=True)
assert wz.current_step_idx == 2
assert wz.current_step == wz.steps[-1]
def test_wizard_fast_forward_with_error(mocker):
mocked_app = mocker.MagicMock()
- mocker.patch('interrogatio.widgets.wizard.get_app', return_value=mocked_app)
+ mocker.patch("interrogatio.widgets.wizard.get_app", return_value=mocked_app)
questions = [
{
- 'name': 'question1',
- 'type': 'input',
- 'message': 'message',
- 'description': 'description',
- 'default': 'value',
- 'validators': [{'name': 'required'}],
+ "name": "question1",
+ "type": "input",
+ "message": "message",
+ "description": "description",
+ "default": "value",
+ "validators": [{"name": "required"}],
},
{
- 'name': 'question2',
- 'type': 'input',
- 'message': 'message',
- 'description': 'description',
- 'validators': [{'name': 'required'}],
- 'disabled': True,
+ "name": "question2",
+ "type": "input",
+ "message": "message",
+ "description": "description",
+ "validators": [{"name": "required"}],
+ "disabled": True,
},
{
- 'name': 'question3',
- 'type': 'input',
- 'message': 'message',
- 'description': 'description',
- 'validators': [{'name': 'required'}],
+ "name": "question3",
+ "type": "input",
+ "message": "message",
+ "description": "description",
+ "validators": [{"name": "required"}],
},
]
handlers = [get_instance(q) for q in questions]
mocker.patch.object(
WizardDialog,
- 'validate',
+ "validate",
side_effect=[True, True, False],
)
- wz = WizardDialog('title', handlers, summary=True, fast_forward=True)
+ wz = WizardDialog("title", handlers, summary=True, fast_forward=True)
assert wz.current_step_idx == 2
assert wz.current_step == wz.steps[2]