From a596894f2d782b9df54c026696e55da1267f7936 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sat, 4 Nov 2023 19:52:12 +0100 Subject: Adding upstream version 1.14.0. Signed-off-by: Daniel Baumann --- .bumpversion.cfg | 2 +- .dockerignore | 7 + .github/workflows/test.yaml | 3 +- CHANGELOG.md | 31 ++- Dockerfile | 28 +- README.md | 4 +- iredis/__init__.py | 2 +- iredis/client.py | 11 +- iredis/commands.py | 2 +- iredis/completers.py | 1 - iredis/config.py | 5 +- iredis/data/iredisrc | 4 + iredis/entry.py | 22 +- iredis/markdown.py | 4 +- poetry.lock | 387 +++++++++++----------------- pyproject.toml | 16 +- tests/cli_tests/test_cli_start.py | 8 +- tests/cli_tests/test_command_input.py | 8 +- tests/cli_tests/test_command_restore.py | 6 + tests/cli_tests/test_completer.py | 3 +- tests/cli_tests/test_pager.py | 14 +- tests/conftest.py | 4 +- tests/unittests/test_client.py | 61 +++-- tests/unittests/test_entry.py | 1 - tests/unittests/test_markdown_doc_render.py | 2 +- 25 files changed, 319 insertions(+), 317 deletions(-) create mode 100644 .dockerignore create mode 100644 tests/cli_tests/test_command_restore.py diff --git a/.bumpversion.cfg b/.bumpversion.cfg index c81c530..9ef25fa 100644 --- a/.bumpversion.cfg +++ b/.bumpversion.cfg @@ -1,5 +1,5 @@ [bumpversion] -current_version = 1.13.1 +current_version = 1.14.0 commit = True tag = True diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..51a2276 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,7 @@ +tests +scripts +CHANGELOG.md +Dockerfile +docs +pyoxidizer.template.bzl +redis-doc diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index 01a9dfd..9516dd9 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -10,10 +10,11 @@ jobs: test: name: Pytest strategy: + fail-fast: false matrix: os: ["ubuntu-20.04"] python: ["3.7", "3.8", "3.9", "3.10", "3.11.1"] - redis: [5, 6, 7] + redis: [5, 6, 7, 7.2] runs-on: ${{ matrix.os }} services: diff --git a/CHANGELOG.md b/CHANGELOG.md index 49329ca..c98e9f2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,15 +1,32 @@ ## UPCOMING -## 1.3 +## 1.14 + +- Dependency: upgrade redis-py to 5 (thanks to [chayim]) +- Feature: porting to redis-server 7.2 now +- Feature: supports python 3.10, 3.11 now +- Doc: update commands.json from redis-doc to latest version + +## 1.13.2 + +- Dependency: upgrade markdown render mistune to v3 +- Dependency: deprecated importlib_resources, use Python build in + `importlib.resources` now +- Dependency: upgrade redis-py to 4.5 +- Doc: update homepage link to iredis.xbin.io +- Bugfix: Fix restore command caused by string literal escape + +## 1.13 - Dependency: Drop Python 3.6 support. - Bugfix: fix some typos. ### 1.12.2 -- Feature: IRedis now honors the `ssl_cert_reqs` strategy, either specifying it via - command line (`--verify-ssl=`) or as an url parameter (`ssl_cert_reqs`) - when the connection is secured via tls (`rediss://`). (authored by [torrefatto]) +- Feature: IRedis now honors the `ssl_cert_reqs` strategy, either specifying it + via command line (`--verify-ssl=`) or as an url + parameter (`ssl_cert_reqs`) when the connection is secured via tls + (`rediss://`). (authored by [torrefatto]) ### 1.12.1 @@ -17,7 +34,8 @@ - Bugfix: all tests pass on redis:7 now. - Feature: IRedis now accept `username` for auth, redis server version under 6 will ignore `username`. -- Feature: IRedis support prompt now, you can customize prompt string. (thanks to [aymericbeaumet]) +- Feature: IRedis support prompt now, you can customize prompt string. (thanks + to [aymericbeaumet]) ## 1.12 @@ -270,7 +288,7 @@ ### 0.8.12 -- Bugfix: Multi spaces between commands can be recongnised as correct commands +- Bugfix: Multi spaces between commands can be recognised as correct commands now. - Feature: Warning on dangerous command. @@ -308,3 +326,4 @@ [tssujt]: https://github.com/tssujt [aymericbeaumet]: https://github.com/aymericbeaumet [torrefatto]: https://github.com/torrefatto +[chayim]: https://github.com/chayim diff --git a/Dockerfile b/Dockerfile index 99c0463..a0baf16 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,18 +1,16 @@ -FROM python:3 +FROM redis/redis-stack-server:latest -WORKDIR /iredis -COPY README.md poetry.lock pyproject.toml ./ -COPY iredis ./iredis - -RUN apt-get update && apt-get install -y --allow-unauthenticated \ - redis-server && \ - rm -rf /var/lib/apt/lists/* +COPY . /iredis +RUN apt-get update --fix-missing +RUN apt-get install -yqq python3 python3-pip python-is-python3 +RUN python3 -m pip install poetry +WORKDIR /iredis +RUN poetry config virtualenvs.create false +RUN poetry build +RUN pip install dist/iredis*.tar.gz +WORKDIR / +RUN rm -rf .cache /var/cache/apt +RUN rm -rf /iredis -RUN python3 -m venv iredis_env && \ - . iredis_env/bin/activate && \ - pip install poetry && \ - poetry install --no-dev && \ - rm -rf ~/.cache - -CMD ["sh","-c","redis-server --daemonize yes && . iredis_env/bin/activate && iredis"] +CMD ["sh", "-c", "/opt/redis-stack/bin/redis-stack-server --daemonize yes && iredis"] diff --git a/README.md b/README.md index 11f3cb2..41927fc 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,7 @@

Github Action PyPI version -Python version +Python version Download stats

@@ -64,7 +64,7 @@ like `KEYS *` (see config file. - Hide password for `AUTH` command. - Says "Goodbye!" to you when you exit! -- For full features, please see: [iredis.io](https://www.iredis.io) +- For full features, please see: [iredis.xbin.io](https://www.iredis.xbin.io) ## Install diff --git a/iredis/__init__.py b/iredis/__init__.py index 4b67c39..b9f68ed 100644 --- a/iredis/__init__.py +++ b/iredis/__init__.py @@ -1 +1 @@ -__version__ = "1.13.1" +__version__ = "1.14.0" diff --git a/iredis/client.py b/iredis/client.py index bbdb87c..f7164b8 100644 --- a/iredis/client.py +++ b/iredis/client.py @@ -4,9 +4,10 @@ IRedis client. import re import os import sys +import codecs import logging from subprocess import run -from importlib_resources import read_text +from importlib.resources import read_text from packaging.version import parse as version_parse import redis @@ -94,6 +95,7 @@ class Client: try: self.connection.connect() except Exception as e: + logger.exception("Can not create connection to server") print(str(e), file=sys.stderr) sys.exit(1) if not config.no_info: @@ -282,6 +284,7 @@ class Client: connection.connect() logger.info(f"New connection created, retry on {connection}.") logger.info(f"send_command: {command_name} , {args}") + connection.send_command(command_name, *args) response = connection.read_response() except AuthenticationError: @@ -547,6 +550,12 @@ class Client: if command_name.upper() in ["ZSCAN", "ZPOPMAX", "ZPOPMIN"]: config.withscores = True + # TODO should we using escape_decode on all strings?? + if command_name.upper() == "RESTORE": + for i, a in enumerate(args): + serialized_value = codecs.escape_decode(a)[0] + args[i] = serialized_value + # not a tty if not completer: logger.warning( diff --git a/iredis/commands.py b/iredis/commands.py index fcbe2a4..cf21a54 100644 --- a/iredis/commands.py +++ b/iredis/commands.py @@ -3,7 +3,7 @@ import csv import json import logging import functools -from importlib_resources import read_text, open_text +from importlib.resources import read_text, open_text from .utils import timer, strip_quote_args from .exceptions import InvalidArguments, AmbiguousCommand diff --git a/iredis/completers.py b/iredis/completers.py index e3ebb5a..6f9ecac 100644 --- a/iredis/completers.py +++ b/iredis/completers.py @@ -105,7 +105,6 @@ class TimestampCompleter(Completer): now = pendulum.now() for unit, minimum in self.when_lower_than.items(): if current <= minimum: - if self.future_time: dt = now.add(**{f"{unit}s": current}) offset_text = "later" diff --git a/iredis/config.py b/iredis/config.py index ea27827..4041bb6 100644 --- a/iredis/config.py +++ b/iredis/config.py @@ -1,4 +1,4 @@ -from importlib_resources import path +from importlib.resources import path import os import logging @@ -63,6 +63,8 @@ class Config: self.withscores = False self.version = "Unknown" + self.greetings = True + self.prompt = None def __setter__(self, name, value): @@ -129,5 +131,6 @@ def load_config_files(iredisrc): config.pager = config_obj["main"].get("pager") config.enable_pager = config_obj["main"].as_bool("enable_pager") config.prompt = config_obj["main"].get("prompt") + config.greetings = config_obj["main"].as_bool("greetings") return config_obj diff --git a/iredis/data/iredisrc b/iredis/data/iredisrc index 6db02a7..978aa4b 100644 --- a/iredis/data/iredisrc +++ b/iredis/data/iredisrc @@ -76,6 +76,10 @@ prompt = # History file location history_location = ~/.iredis_history +# if set to True, will display version information on startup +# can set to False to disable it. +greetings = True + [alias_dsn] # example_dsn = redis://[[username]:[password]]@localhost:6379/0 # example_dsn = rediss://[[username]:[password]]@localhost:6379/0 diff --git a/iredis/entry.py b/iredis/entry.py index c7ae76c..0799a07 100644 --- a/iredis/entry.py +++ b/iredis/entry.py @@ -61,8 +61,8 @@ def greetings(): reason = "" server_version = f"redis-server {config.version} {reason}" - home_page = "Home: https://iredis.io" - issues = "Issues: https://iredis.io/issues" + home_page = "Home: https://iredis.xbin.io/" + issues = "Issues: https://github.com/laixintao/iredis/issues" display = "\n".join([iredis_version, server_version, home_page, issues]) if config.raw: display = display.encode() @@ -177,9 +177,9 @@ def repl(client, session, start_time): try: command = session.prompt( prompt_message(client), - bottom_toolbar=BottomToolbar(command_holder).render - if config.bottom_bar - else None, + bottom_toolbar=( + BottomToolbar(command_holder).render if config.bottom_bar else None + ), input_processors=[ UpdateBottomProcessor(command_holder, session), PasswordProcessor(), @@ -274,6 +274,12 @@ VERIFY_SSL_HELP = """Set the TLS certificate verification strategy""" @click.option("--rainbow/--no-rainbow", default=None, is_flag=True, help=RAINBOW) @click.option("--shell/--no-shell", default=None, is_flag=True, help=SHELL) @click.option("--pager/--no-pager", default=None, is_flag=True, help=PAGER_HELP) +@click.option( + "--greetings/--no-greetings", + default=None, + is_flag=True, + help="Enable or disable greeting messages", +) @click.option( "--verify-ssl", default=None, @@ -309,6 +315,7 @@ def gather_args( socket, shell, pager, + greetings, verify_ssl, prompt, ): @@ -354,6 +361,8 @@ def gather_args( config.enable_pager = pager if verify_ssl is not None: config.verify_ssl = verify_ssl + if greetings is not None: + config.greetings = greetings return ctx @@ -492,5 +501,6 @@ def main(): ) # print hello message - greetings() + if config.greetings: + greetings() repl(client, session, enter_main_time) diff --git a/iredis/markdown.py b/iredis/markdown.py index 6f26642..89297ec 100644 --- a/iredis/markdown.py +++ b/iredis/markdown.py @@ -30,7 +30,7 @@ class TerminalRender(mistune.HTMLRenderer): return super().heading(header_text, 2) return super().heading(self._to_title(text), level) - def list(self, body, ordered, level, start=None): + def list(self, body, ordered, *args, **kwargs): """Rendering list tags like ``
    `` and ``
      ``. :param body: body contents of the list. @@ -41,7 +41,7 @@ class TerminalRender(mistune.HTMLRenderer): tag = "ol" return "<%s>%s\n" % (tag, body, tag) - def list_item(self, text, level): + def list_item(self, text, *args): """Rendering list item snippet. Like ``
    1. ``.""" return "
    2. * %s
    3. \n" % text diff --git a/poetry.lock b/poetry.lock index ab14deb..752359a 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,75 +1,83 @@ +# This file is automatically @generated by Poetry 1.5.1 and should not be changed by hand. + [[package]] name = "async-timeout" -version = "4.0.2" +version = "4.0.3" description = "Timeout context manager for asyncio programs" -category = "main" optional = false -python-versions = ">=3.6" +python-versions = ">=3.7" +files = [ + {file = "async-timeout-4.0.3.tar.gz", hash = "sha256:4640d96be84d82d02ed59ea2b7105a0f7b33abe8703703cd0ab0bf87c427522f"}, + {file = "async_timeout-4.0.3-py3-none-any.whl", hash = "sha256:7405140ff1230c310e51dc27b3145b9092d659ce68ff733fb0cefe3ee42be028"}, +] [package.dependencies] typing-extensions = {version = ">=3.6.5", markers = "python_version < \"3.8\""} -[[package]] -name = "attrs" -version = "22.2.0" -description = "Classes Without Boilerplate" -category = "dev" -optional = false -python-versions = ">=3.6" - -[package.extras] -cov = ["attrs[tests]", "coverage-enable-subprocess", "coverage[toml] (>=5.3)"] -dev = ["attrs[docs,tests]"] -docs = ["furo", "myst-parser", "sphinx", "sphinx-notfound-page", "sphinxcontrib-towncrier", "towncrier", "zope.interface"] -tests = ["attrs[tests-no-zope]", "zope.interface"] -tests-no-zope = ["cloudpickle", "hypothesis", "mypy (>=0.971,<0.990)", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "pytest-xdist[psutil]"] -tests_no_zope = ["cloudpickle", "hypothesis", "mypy (>=0.971,<0.990)", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "pytest-xdist[psutil]"] - [[package]] name = "click" -version = "7.1.2" +version = "8.1.7" description = "Composable command line interface toolkit" -category = "main" optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" +python-versions = ">=3.7" +files = [ + {file = "click-8.1.7-py3-none-any.whl", hash = "sha256:ae74fb96c20a0277a1d615f1e4d73c8414f5a98db8b799a7931d1582f3390c28"}, + {file = "click-8.1.7.tar.gz", hash = "sha256:ca9853ad459e787e2192211578cc907e7594e294c7ccc834310722b41b9ca6de"}, +] + +[package.dependencies] +colorama = {version = "*", markers = "platform_system == \"Windows\""} +importlib-metadata = {version = "*", markers = "python_version < \"3.8\""} [[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 = [ + {file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"}, + {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"}, +] [[package]] name = "configobj" -version = "5.0.6" +version = "5.0.8" description = "Config file reading, writing and validation." -category = "main" optional = false -python-versions = "*" +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" +files = [ + {file = "configobj-5.0.8-py2.py3-none-any.whl", hash = "sha256:a7a8c6ab7daade85c3f329931a807c8aee750a2494363934f8ea84d8a54c87ea"}, + {file = "configobj-5.0.8.tar.gz", hash = "sha256:6f704434a07dc4f4dc7c9a745172c1cad449feb548febd9f7fe362629c627a97"}, +] [package.dependencies] six = "*" [[package]] name = "exceptiongroup" -version = "1.1.0" +version = "1.1.3" description = "Backport of PEP 654 (exception groups)" -category = "dev" optional = false python-versions = ">=3.7" +files = [ + {file = "exceptiongroup-1.1.3-py3-none-any.whl", hash = "sha256:343280667a4585d195ca1cf9cef84a4e178c4b6cf2274caef9859782b567d5e3"}, + {file = "exceptiongroup-1.1.3.tar.gz", hash = "sha256:097acd85d473d75af5bb98e41b61ff7fe35efe6675e4f9370ec6ec5126d160e9"}, +] [package.extras] test = ["pytest (>=6)"] [[package]] name = "importlib-metadata" -version = "5.2.0" +version = "6.7.0" description = "Read metadata from Python packages" -category = "main" optional = false python-versions = ">=3.7" +files = [ + {file = "importlib_metadata-6.7.0-py3-none-any.whl", hash = "sha256:cb52082e659e97afc5dac71e79de97d8681de3aa07ff18578330904a9d18e5b5"}, + {file = "importlib_metadata-6.7.0.tar.gz", hash = "sha256:1aaf550d4f73e5d6783e7acb77aec43d49da8017410afae93822cc9cca98c4d4"}, +] [package.dependencies] typing-extensions = {version = ">=3.6.4", markers = "python_version < \"3.8\""} @@ -78,57 +86,70 @@ zipp = ">=0.5" [package.extras] docs = ["furo", "jaraco.packaging (>=9)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"] perf = ["ipython"] -testing = ["flake8 (<5)", "flufl.flake8", "importlib-resources (>=1.3)", "packaging", "pyfakefs", "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 (>=0.9.2)"] - -[[package]] -name = "importlib-resources" -version = "5.10.2" -description = "Read resources from Python packages" -category = "main" -optional = false -python-versions = ">=3.7" - -[package.dependencies] -zipp = {version = ">=3.1.0", markers = "python_version < \"3.10\""} - -[package.extras] -docs = ["furo", "jaraco.packaging (>=9)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"] -testing = ["flake8 (<5)", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=1.3)", "pytest-flake8", "pytest-mypy (>=0.9.1)"] +testing = ["flufl.flake8", "importlib-resources (>=1.3)", "packaging", "pyfakefs", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=1.3)", "pytest-mypy (>=0.9.1)", "pytest-perf (>=0.9.2)", "pytest-ruff"] [[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-2.0.0-py3-none-any.whl", hash = "sha256:b6a85871a79d2e3b22d2d1b94ac2824226a63c6b741c88f7ae975f18b6778374"}, + {file = "iniconfig-2.0.0.tar.gz", hash = "sha256:2d91e135bf72d31a410b17c16da610a82cb55f6b0477d1a902134b24a455b8b3"}, +] [[package]] name = "mistune" -version = "2.0.4" -description = "A sane Markdown parser with useful plugins and renderers" -category = "main" +version = "3.0.2" +description = "A sane and fast Markdown parser with useful plugins and renderers" optional = false -python-versions = "*" +python-versions = ">=3.7" +files = [ + {file = "mistune-3.0.2-py3-none-any.whl", hash = "sha256:71481854c30fdbc938963d3605b72501f5c10a9320ecd412c121c163a1c7d205"}, + {file = "mistune-3.0.2.tar.gz", hash = "sha256:fc7f93ded930c92394ef2cb6f04a8aabab4117a91449e72dcc8dfa646a508be8"}, +] [[package]] name = "packaging" -version = "21.3" +version = "23.2" description = "Core utilities for Python packages" -category = "main" optional = false -python-versions = ">=3.6" - -[package.dependencies] -pyparsing = ">=2.0.2,<3.0.5 || >3.0.5" +python-versions = ">=3.7" +files = [ + {file = "packaging-23.2-py3-none-any.whl", hash = "sha256:8c491190033a9af7e1d931d0b5dacc2ef47509b34dd0de67ed209b5203fc88c7"}, + {file = "packaging-23.2.tar.gz", hash = "sha256:048fb0e9405036518eaaf48a55953c750c11e1a1b68e0dd1a9d62ed0c092cfc5"}, +] [[package]] name = "pendulum" version = "2.1.2" description = "Python datetimes made easy" -category = "main" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" +files = [ + {file = "pendulum-2.1.2-cp27-cp27m-macosx_10_15_x86_64.whl", hash = "sha256:b6c352f4bd32dff1ea7066bd31ad0f71f8d8100b9ff709fb343f3b86cee43efe"}, + {file = "pendulum-2.1.2-cp27-cp27m-win_amd64.whl", hash = "sha256:318f72f62e8e23cd6660dbafe1e346950281a9aed144b5c596b2ddabc1d19739"}, + {file = "pendulum-2.1.2-cp35-cp35m-macosx_10_15_x86_64.whl", hash = "sha256:0731f0c661a3cb779d398803655494893c9f581f6488048b3fb629c2342b5394"}, + {file = "pendulum-2.1.2-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:3481fad1dc3f6f6738bd575a951d3c15d4b4ce7c82dce37cf8ac1483fde6e8b0"}, + {file = "pendulum-2.1.2-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:9702069c694306297ed362ce7e3c1ef8404ac8ede39f9b28b7c1a7ad8c3959e3"}, + {file = "pendulum-2.1.2-cp35-cp35m-win_amd64.whl", hash = "sha256:fb53ffa0085002ddd43b6ca61a7b34f2d4d7c3ed66f931fe599e1a531b42af9b"}, + {file = "pendulum-2.1.2-cp36-cp36m-macosx_10_15_x86_64.whl", hash = "sha256:c501749fdd3d6f9e726086bf0cd4437281ed47e7bca132ddb522f86a1645d360"}, + {file = "pendulum-2.1.2-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:c807a578a532eeb226150d5006f156632df2cc8c5693d778324b43ff8c515dd0"}, + {file = "pendulum-2.1.2-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:2d1619a721df661e506eff8db8614016f0720ac171fe80dda1333ee44e684087"}, + {file = "pendulum-2.1.2-cp36-cp36m-win_amd64.whl", hash = "sha256:f888f2d2909a414680a29ae74d0592758f2b9fcdee3549887779cd4055e975db"}, + {file = "pendulum-2.1.2-cp37-cp37m-macosx_10_15_x86_64.whl", hash = "sha256:e95d329384717c7bf627bf27e204bc3b15c8238fa8d9d9781d93712776c14002"}, + {file = "pendulum-2.1.2-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:4c9c689747f39d0d02a9f94fcee737b34a5773803a64a5fdb046ee9cac7442c5"}, + {file = "pendulum-2.1.2-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:1245cd0075a3c6d889f581f6325dd8404aca5884dea7223a5566c38aab94642b"}, + {file = "pendulum-2.1.2-cp37-cp37m-win_amd64.whl", hash = "sha256:db0a40d8bcd27b4fb46676e8eb3c732c67a5a5e6bfab8927028224fbced0b40b"}, + {file = "pendulum-2.1.2-cp38-cp38-macosx_10_15_x86_64.whl", hash = "sha256:f5e236e7730cab1644e1b87aca3d2ff3e375a608542e90fe25685dae46310116"}, + {file = "pendulum-2.1.2-cp38-cp38-manylinux1_i686.whl", hash = "sha256:de42ea3e2943171a9e95141f2eecf972480636e8e484ccffaf1e833929e9e052"}, + {file = "pendulum-2.1.2-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:7c5ec650cb4bec4c63a89a0242cc8c3cebcec92fcfe937c417ba18277d8560be"}, + {file = "pendulum-2.1.2-cp38-cp38-win_amd64.whl", hash = "sha256:33fb61601083f3eb1d15edeb45274f73c63b3c44a8524703dc143f4212bf3269"}, + {file = "pendulum-2.1.2-cp39-cp39-manylinux1_i686.whl", hash = "sha256:29c40a6f2942376185728c9a0347d7c0f07905638c83007e1d262781f1e6953a"}, + {file = "pendulum-2.1.2-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:94b1fc947bfe38579b28e1cccb36f7e28a15e841f30384b5ad6c5e31055c85d7"}, + {file = "pendulum-2.1.2.tar.gz", hash = "sha256:b06a0ca1bfe41c990bbf0c029f0b6501a7f2ec4e38bfec730712015e8860f207"}, +] [package.dependencies] python-dateutil = ">=2.6,<3.0" @@ -138,20 +159,26 @@ pytzdata = ">=2020.1" name = "pexpect" version = "4.8.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"}, +] [package.dependencies] ptyprocess = ">=0.5" [[package]] name = "pluggy" -version = "1.0.0" +version = "1.2.0" description = "plugin and hook calling mechanisms for python" -category = "dev" optional = false -python-versions = ">=3.6" +python-versions = ">=3.7" +files = [ + {file = "pluggy-1.2.0-py3-none-any.whl", hash = "sha256:c2fd55a7d7a3863cba1a013e4e2414658b1d07b6bc57b3919e0c63c9abb99849"}, + {file = "pluggy-1.2.0.tar.gz", hash = "sha256:d12f0c4b579b15f5e054301bb226ee85eeeba08ffec228092f8defbaa3a4c4b3"}, +] [package.dependencies] importlib-metadata = {version = ">=0.12", markers = "python_version < \"3.8\""} @@ -162,11 +189,14 @@ testing = ["pytest", "pytest-benchmark"] [[package]] name = "prompt-toolkit" -version = "3.0.36" +version = "3.0.39" 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.39-py3-none-any.whl", hash = "sha256:9dffbe1d8acf91e3de75f3b544e4842382fc06c6babe903ac9acb74dc6e08d88"}, + {file = "prompt_toolkit-3.0.39.tar.gz", hash = "sha256:04505ade687dc26dc4284b1ad19a83be2f2afe83e7a828ace0c72f3a1df72aac"}, +] [package.dependencies] wcwidth = "*" @@ -175,42 +205,39 @@ wcwidth = "*" name = "ptyprocess" version = "0.7.0" description = "Run a subprocess in a pseudo terminal" -category = "dev" optional = false python-versions = "*" +files = [ + {file = "ptyprocess-0.7.0-py2.py3-none-any.whl", hash = "sha256:4b41f3967fce3af57cc7e94b888626c18bf37a083e3651ca8feeb66d492fef35"}, + {file = "ptyprocess-0.7.0.tar.gz", hash = "sha256:5c5d0a3b48ceee0b48485e0c26037c0acd7d29765ca3fbb5cb3831d347423220"}, +] [[package]] -name = "Pygments" -version = "2.13.0" +name = "pygments" +version = "2.16.1" description = "Pygments is a syntax highlighting package written in Python." -category = "main" optional = false -python-versions = ">=3.6" +python-versions = ">=3.7" +files = [ + {file = "Pygments-2.16.1-py3-none-any.whl", hash = "sha256:13fc09fa63bc8d8671a6d247e1eb303c4b343eaee81d861f3404db2935653692"}, + {file = "Pygments-2.16.1.tar.gz", hash = "sha256:1daff0494820c69bc8941e407aa20f577374ee88364ee10a98fdbe0aece96e29"}, +] [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 = "main" -optional = false -python-versions = ">=3.6.8" - -[package.extras] -diagrams = ["jinja2", "railroad-diagrams"] - [[package]] name = "pytest" -version = "7.2.0" +version = "7.4.3" description = "pytest: simple powerful testing with Python" -category = "dev" optional = false python-versions = ">=3.7" +files = [ + {file = "pytest-7.4.3-py3-none-any.whl", hash = "sha256:0d009c083ea859a71b76adf7c1d502e4bc170b80a8ef002da5806527b9591fac"}, + {file = "pytest-7.4.3.tar.gz", hash = "sha256:d989d136982de4e3b29dabcc838ad581c64e8ed52c11fbe86ddebd9da0818cd5"}, +] [package.dependencies] -attrs = ">=19.2.0" colorama = {version = "*", markers = "sys_platform == \"win32\""} exceptiongroup = {version = ">=1.0.0rc8", markers = "python_version < \"3.11\""} importlib-metadata = {version = ">=0.12", markers = "python_version < \"3.8\""} @@ -220,15 +247,18 @@ 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 = "python-dateutil" version = "2.8.2" description = "Extensions to the standard Python datetime module" -category = "main" optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7" +files = [ + {file = "python-dateutil-2.8.2.tar.gz", hash = "sha256:0123cacc1627ae19ddf3c27a5de5bd67ee4586fbdd6440d9748f8abb483d3e86"}, + {file = "python_dateutil-2.8.2-py2.py3-none-any.whl", hash = "sha256:961d03dc3453ebbc59dbdea9e4e11c5651520a876d0f4db161e8674aae935da9"}, +] [package.dependencies] six = ">=1.5" @@ -237,20 +267,26 @@ six = ">=1.5" name = "pytzdata" version = "2020.1" description = "The Olson timezone database for Python." -category = "main" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" +files = [ + {file = "pytzdata-2020.1-py2.py3-none-any.whl", hash = "sha256:e1e14750bcf95016381e4d472bad004eef710f2d6417240904070b3d6654485f"}, + {file = "pytzdata-2020.1.tar.gz", hash = "sha256:3efa13b335a00a8de1d345ae41ec78dd11c9f8807f522d39850f2dd828681540"}, +] [[package]] name = "redis" -version = "4.4.0" +version = "5.0.1" description = "Python client for Redis database and key-value store" -category = "main" optional = false python-versions = ">=3.7" +files = [ + {file = "redis-5.0.1-py3-none-any.whl", hash = "sha256:ed4802971884ae19d640775ba3b03aa2e7bd5e8fb8dfaed2decce4d0fc48391f"}, + {file = "redis-5.0.1.tar.gz", hash = "sha256:0dab495cd5753069d3bc650a0dde8a8f9edde16fc5691b689a566eda58100d0f"}, +] [package.dependencies] -async-timeout = ">=4.0.2" +async-timeout = {version = ">=4.0.2", markers = "python_full_version <= \"3.11.2\""} importlib-metadata = {version = ">=1.0", markers = "python_version < \"3.8\""} typing-extensions = {version = "*", markers = "python_version < \"3.8\""} @@ -262,175 +298,62 @@ ocsp = ["cryptography (>=36.0.1)", "pyopenssl (==20.0.1)", "requests (>=2.26.0)" name = "six" version = "1.16.0" description = "Python 2 and 3 compatibility utilities" -category = "main" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*" +files = [ + {file = "six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"}, + {file = "six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926"}, +] [[package]] name = "tomli" version = "2.0.1" description = "A lil' TOML parser" -category = "dev" optional = false python-versions = ">=3.7" +files = [ + {file = "tomli-2.0.1-py3-none-any.whl", hash = "sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc"}, + {file = "tomli-2.0.1.tar.gz", hash = "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f"}, +] [[package]] name = "typing-extensions" -version = "4.4.0" +version = "4.7.1" description = "Backported and Experimental Type Hints for Python 3.7+" -category = "main" optional = false python-versions = ">=3.7" +files = [ + {file = "typing_extensions-4.7.1-py3-none-any.whl", hash = "sha256:440d5dd3af93b060174bf433bccd69b0babc3b15b1a8dca43789fd7f61514b36"}, + {file = "typing_extensions-4.7.1.tar.gz", hash = "sha256:b75ddc264f0ba5615db7ba217daeb99701ad295353c45f9e95963337ceeeffb2"}, +] [[package]] name = "wcwidth" version = "0.1.9" description = "Measures number of Terminal column cells of wide-character codes" -category = "main" optional = false python-versions = "*" +files = [ + {file = "wcwidth-0.1.9-py2.py3-none-any.whl", hash = "sha256:cafe2186b3c009a04067022ce1dcd79cb38d8d65ee4f4791b8888d6599d1bbe1"}, + {file = "wcwidth-0.1.9.tar.gz", hash = "sha256:ee73862862a156bf77ff92b09034fc4825dd3af9cf81bc5b360668d425f3c5f1"}, +] [[package]] name = "zipp" -version = "3.11.0" +version = "3.15.0" description = "Backport of pathlib-compatible object wrapper for zip files" -category = "main" optional = false python-versions = ">=3.7" +files = [ + {file = "zipp-3.15.0-py3-none-any.whl", hash = "sha256:48904fc76a60e542af151aded95726c1a5c34ed43ab4134b597665c86d7ad556"}, + {file = "zipp-3.15.0.tar.gz", hash = "sha256:112929ad649da941c23de50f356a2b5570c954b65150642bccdd66bf194d224b"}, +] [package.extras] -docs = ["furo", "jaraco.packaging (>=9)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)"] -testing = ["flake8 (<5)", "func-timeout", "jaraco.functools", "jaraco.itertools", "more-itertools", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=1.3)", "pytest-flake8", "pytest-mypy (>=0.9.1)"] +docs = ["furo", "jaraco.packaging (>=9)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"] +testing = ["big-O", "flake8 (<5)", "jaraco.functools", "jaraco.itertools", "more-itertools", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=1.3)", "pytest-flake8", "pytest-mypy (>=0.9.1)"] [metadata] -lock-version = "1.1" +lock-version = "2.0" python-versions = "^3.7" -content-hash = "6ad42fae2cc7eab35a27500c86a45fffef1d406d3f324f173c56aee107d8a480" - -[metadata.files] -async-timeout = [ - {file = "async-timeout-4.0.2.tar.gz", hash = "sha256:2163e1640ddb52b7a8c80d0a67a08587e5d245cc9c553a74a847056bc2976b15"}, - {file = "async_timeout-4.0.2-py3-none-any.whl", hash = "sha256:8ca1e4fcf50d07413d66d1a5e416e42cfdf5851c981d679a09851a6853383b3c"}, -] -attrs = [ - {file = "attrs-22.2.0-py3-none-any.whl", hash = "sha256:29e95c7f6778868dbd49170f98f8818f78f3dc5e0e37c0b1f474e3561b240836"}, - {file = "attrs-22.2.0.tar.gz", hash = "sha256:c9227bfc2f01993c03f68db37d1d15c9690188323c067c641f1a35ca58185f99"}, -] -click = [ - {file = "click-7.1.2-py2.py3-none-any.whl", hash = "sha256:dacca89f4bfadd5de3d7489b7c8a566eee0d3676333fbb50030263894c38c0dc"}, - {file = "click-7.1.2.tar.gz", hash = "sha256:d2b5255c7c6349bc1bd1e59e08cd12acbbd63ce649f2588755783aa94dfb6b1a"}, -] -colorama = [ - {file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"}, - {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"}, -] -configobj = [ - {file = "configobj-5.0.6.tar.gz", hash = "sha256:a2f5650770e1c87fb335af19a9b7eb73fc05ccf22144eb68db7d00cd2bcb0902"}, -] -exceptiongroup = [ - {file = "exceptiongroup-1.1.0-py3-none-any.whl", hash = "sha256:327cbda3da756e2de031a3107b81ab7b3770a602c4d16ca618298c526f4bec1e"}, - {file = "exceptiongroup-1.1.0.tar.gz", hash = "sha256:bcb67d800a4497e1b404c2dd44fca47d3b7a5e5433dbab67f96c1a685cdfdf23"}, -] -importlib-metadata = [ - {file = "importlib_metadata-5.2.0-py3-none-any.whl", hash = "sha256:0eafa39ba42bf225fc00e67f701d71f85aead9f878569caf13c3724f704b970f"}, - {file = "importlib_metadata-5.2.0.tar.gz", hash = "sha256:404d48d62bba0b7a77ff9d405efd91501bef2e67ff4ace0bed40a0cf28c3c7cd"}, -] -importlib-resources = [ - {file = "importlib_resources-5.10.2-py3-none-any.whl", hash = "sha256:7d543798b0beca10b6a01ac7cafda9f822c54db9e8376a6bf57e0cbd74d486b6"}, - {file = "importlib_resources-5.10.2.tar.gz", hash = "sha256:e4a96c8cc0339647ff9a5e0550d9f276fc5a01ffa276012b58ec108cfd7b8484"}, -] -iniconfig = [ - {file = "iniconfig-1.1.1-py2.py3-none-any.whl", hash = "sha256:011e24c64b7f47f6ebd835bb12a743f2fbe9a26d4cecaa7f53bc4f35ee9da8b3"}, - {file = "iniconfig-1.1.1.tar.gz", hash = "sha256:bc3af051d7d14b2ee5ef9969666def0cd1a000e121eaea580d4a313df4b37f32"}, -] -mistune = [ - {file = "mistune-2.0.4-py2.py3-none-any.whl", hash = "sha256:182cc5ee6f8ed1b807de6b7bb50155df7b66495412836b9a74c8fbdfc75fe36d"}, - {file = "mistune-2.0.4.tar.gz", hash = "sha256:9ee0a66053e2267aba772c71e06891fa8f1af6d4b01d5e84e267b4570d4d9808"}, -] -packaging = [ - {file = "packaging-21.3-py3-none-any.whl", hash = "sha256:ef103e05f519cdc783ae24ea4e2e0f508a9c99b2d4969652eed6a2e1ea5bd522"}, - {file = "packaging-21.3.tar.gz", hash = "sha256:dd47c42927d89ab911e606518907cc2d3a1f38bbd026385970643f9c5b8ecfeb"}, -] -pendulum = [ - {file = "pendulum-2.1.2-cp27-cp27m-macosx_10_15_x86_64.whl", hash = "sha256:b6c352f4bd32dff1ea7066bd31ad0f71f8d8100b9ff709fb343f3b86cee43efe"}, - {file = "pendulum-2.1.2-cp27-cp27m-win_amd64.whl", hash = "sha256:318f72f62e8e23cd6660dbafe1e346950281a9aed144b5c596b2ddabc1d19739"}, - {file = "pendulum-2.1.2-cp35-cp35m-macosx_10_15_x86_64.whl", hash = "sha256:0731f0c661a3cb779d398803655494893c9f581f6488048b3fb629c2342b5394"}, - {file = "pendulum-2.1.2-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:3481fad1dc3f6f6738bd575a951d3c15d4b4ce7c82dce37cf8ac1483fde6e8b0"}, - {file = "pendulum-2.1.2-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:9702069c694306297ed362ce7e3c1ef8404ac8ede39f9b28b7c1a7ad8c3959e3"}, - {file = "pendulum-2.1.2-cp35-cp35m-win_amd64.whl", hash = "sha256:fb53ffa0085002ddd43b6ca61a7b34f2d4d7c3ed66f931fe599e1a531b42af9b"}, - {file = "pendulum-2.1.2-cp36-cp36m-macosx_10_15_x86_64.whl", hash = "sha256:c501749fdd3d6f9e726086bf0cd4437281ed47e7bca132ddb522f86a1645d360"}, - {file = "pendulum-2.1.2-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:c807a578a532eeb226150d5006f156632df2cc8c5693d778324b43ff8c515dd0"}, - {file = "pendulum-2.1.2-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:2d1619a721df661e506eff8db8614016f0720ac171fe80dda1333ee44e684087"}, - {file = "pendulum-2.1.2-cp36-cp36m-win_amd64.whl", hash = "sha256:f888f2d2909a414680a29ae74d0592758f2b9fcdee3549887779cd4055e975db"}, - {file = "pendulum-2.1.2-cp37-cp37m-macosx_10_15_x86_64.whl", hash = "sha256:e95d329384717c7bf627bf27e204bc3b15c8238fa8d9d9781d93712776c14002"}, - {file = "pendulum-2.1.2-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:4c9c689747f39d0d02a9f94fcee737b34a5773803a64a5fdb046ee9cac7442c5"}, - {file = "pendulum-2.1.2-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:1245cd0075a3c6d889f581f6325dd8404aca5884dea7223a5566c38aab94642b"}, - {file = "pendulum-2.1.2-cp37-cp37m-win_amd64.whl", hash = "sha256:db0a40d8bcd27b4fb46676e8eb3c732c67a5a5e6bfab8927028224fbced0b40b"}, - {file = "pendulum-2.1.2-cp38-cp38-macosx_10_15_x86_64.whl", hash = "sha256:f5e236e7730cab1644e1b87aca3d2ff3e375a608542e90fe25685dae46310116"}, - {file = "pendulum-2.1.2-cp38-cp38-manylinux1_i686.whl", hash = "sha256:de42ea3e2943171a9e95141f2eecf972480636e8e484ccffaf1e833929e9e052"}, - {file = "pendulum-2.1.2-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:7c5ec650cb4bec4c63a89a0242cc8c3cebcec92fcfe937c417ba18277d8560be"}, - {file = "pendulum-2.1.2-cp38-cp38-win_amd64.whl", hash = "sha256:33fb61601083f3eb1d15edeb45274f73c63b3c44a8524703dc143f4212bf3269"}, - {file = "pendulum-2.1.2-cp39-cp39-manylinux1_i686.whl", hash = "sha256:29c40a6f2942376185728c9a0347d7c0f07905638c83007e1d262781f1e6953a"}, - {file = "pendulum-2.1.2-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:94b1fc947bfe38579b28e1cccb36f7e28a15e841f30384b5ad6c5e31055c85d7"}, - {file = "pendulum-2.1.2.tar.gz", hash = "sha256:b06a0ca1bfe41c990bbf0c029f0b6501a7f2ec4e38bfec730712015e8860f207"}, -] -pexpect = [ - {file = "pexpect-4.8.0-py2.py3-none-any.whl", hash = "sha256:0b48a55dcb3c05f3329815901ea4fc1537514d6ba867a152b581d69ae3710937"}, - {file = "pexpect-4.8.0.tar.gz", hash = "sha256:fc65a43959d153d0114afe13997d439c22823a27cefceb5ff35c2178c6784c0c"}, -] -pluggy = [ - {file = "pluggy-1.0.0-py2.py3-none-any.whl", hash = "sha256:74134bbf457f031a36d68416e1509f34bd5ccc019f0bcc952c7b909d06b37bd3"}, - {file = "pluggy-1.0.0.tar.gz", hash = "sha256:4224373bacce55f955a878bf9cfa763c1e360858e330072059e10bad68531159"}, -] -prompt-toolkit = [ - {file = "prompt_toolkit-3.0.36-py3-none-any.whl", hash = "sha256:aa64ad242a462c5ff0363a7b9cfe696c20d55d9fc60c11fd8e632d064804d305"}, - {file = "prompt_toolkit-3.0.36.tar.gz", hash = "sha256:3e163f254bef5a03b146397d7c1963bd3e2812f0964bb9a24e6ec761fd28db63"}, -] -ptyprocess = [ - {file = "ptyprocess-0.7.0-py2.py3-none-any.whl", hash = "sha256:4b41f3967fce3af57cc7e94b888626c18bf37a083e3651ca8feeb66d492fef35"}, - {file = "ptyprocess-0.7.0.tar.gz", hash = "sha256:5c5d0a3b48ceee0b48485e0c26037c0acd7d29765ca3fbb5cb3831d347423220"}, -] -Pygments = [ - {file = "Pygments-2.13.0-py3-none-any.whl", hash = "sha256:f643f331ab57ba3c9d89212ee4a2dabc6e94f117cf4eefde99a0574720d14c42"}, - {file = "Pygments-2.13.0.tar.gz", hash = "sha256:56a8508ae95f98e2b9bdf93a6be5ae3f7d8af858b43e02c5a2ff083726be40c1"}, -] -pyparsing = [ - {file = "pyparsing-3.0.9-py3-none-any.whl", hash = "sha256:5026bae9a10eeaefb61dab2f09052b9f4307d44aee4eda64b309723d8d206bbc"}, - {file = "pyparsing-3.0.9.tar.gz", hash = "sha256:2b020ecf7d21b687f219b71ecad3631f644a47f01403fa1d1036b0c6416d70fb"}, -] -pytest = [ - {file = "pytest-7.2.0-py3-none-any.whl", hash = "sha256:892f933d339f068883b6fd5a459f03d85bfcb355e4981e146d2c7616c21fef71"}, - {file = "pytest-7.2.0.tar.gz", hash = "sha256:c4014eb40e10f11f355ad4e3c2fb2c6c6d1919c73f3b5a433de4708202cade59"}, -] -python-dateutil = [ - {file = "python-dateutil-2.8.2.tar.gz", hash = "sha256:0123cacc1627ae19ddf3c27a5de5bd67ee4586fbdd6440d9748f8abb483d3e86"}, - {file = "python_dateutil-2.8.2-py2.py3-none-any.whl", hash = "sha256:961d03dc3453ebbc59dbdea9e4e11c5651520a876d0f4db161e8674aae935da9"}, -] -pytzdata = [ - {file = "pytzdata-2020.1-py2.py3-none-any.whl", hash = "sha256:e1e14750bcf95016381e4d472bad004eef710f2d6417240904070b3d6654485f"}, - {file = "pytzdata-2020.1.tar.gz", hash = "sha256:3efa13b335a00a8de1d345ae41ec78dd11c9f8807f522d39850f2dd828681540"}, -] -redis = [ - {file = "redis-4.4.0-py3-none-any.whl", hash = "sha256:cae3ee5d1f57d8caf534cd8764edf3163c77e073bdd74b6f54a87ffafdc5e7d9"}, - {file = "redis-4.4.0.tar.gz", hash = "sha256:7b8c87d19c45d3f1271b124858d2a5c13160c4e74d4835e28273400fa34d5228"}, -] -six = [ - {file = "six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"}, - {file = "six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926"}, -] -tomli = [ - {file = "tomli-2.0.1-py3-none-any.whl", hash = "sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc"}, - {file = "tomli-2.0.1.tar.gz", hash = "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f"}, -] -typing-extensions = [ - {file = "typing_extensions-4.4.0-py3-none-any.whl", hash = "sha256:16fa4864408f655d35ec496218b85f79b3437c829e93320c7c9215ccfd92489e"}, - {file = "typing_extensions-4.4.0.tar.gz", hash = "sha256:1511434bb92bf8dd198c12b1cc812e800d4181cfcb867674e0f8279cc93087aa"}, -] -wcwidth = [ - {file = "wcwidth-0.1.9-py2.py3-none-any.whl", hash = "sha256:cafe2186b3c009a04067022ce1dcd79cb38d8d65ee4f4791b8888d6599d1bbe1"}, - {file = "wcwidth-0.1.9.tar.gz", hash = "sha256:ee73862862a156bf77ff92b09034fc4825dd3af9cf81bc5b360668d425f3c5f1"}, -] -zipp = [ - {file = "zipp-3.11.0-py3-none-any.whl", hash = "sha256:83a28fcb75844b5c0cdaf5aa4003c2d728c77e05f5aeabe8e95e56727005fbaa"}, - {file = "zipp-3.11.0.tar.gz", hash = "sha256:a7a22e05929290a67401440b39690ae6563279bced5f314609d9d03798f56766"}, -] +content-hash = "33eaaf0e62340be5fa5c74233fd0760e61c9635cbad8f38d625f3c253fb9df4c" diff --git a/pyproject.toml b/pyproject.toml index dc6f68d..088fb45 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "iredis" -version = "1.13.1" +version = "1.14.0" description = "Terminal client for Redis with auto-completion and syntax highlighting." authors = ["laixintao "] readme = 'README.md' @@ -19,6 +19,8 @@ classifiers = [ "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", "Topic :: Database", "License :: OSI Approved :: MIT License", "Intended Audience :: Developers", @@ -26,22 +28,20 @@ classifiers = [ packages = [ { include = "iredis" }, - { include = "tests", format = "sdist" }, ] [tool.poetry.dependencies] python = "^3.7" prompt_toolkit = "^3" Pygments = "^2" -mistune = "^2.0" +mistune = "^3.0" configobj = "^5.0" -click = "^7.0" -pendulum = "^2.0" -importlib-resources = "^5.1.0" +click = "^8.0" +pendulum = "^2.1.0" # wcwidth 0.2.x uses pkg_resources which is not supported by PyOxidizer wcwidth = "0.1.9" -packaging = "^21.3" -redis = "^4.3.4" +packaging = "^23.0" +redis = "^5.0.0" [tool.poetry.dev-dependencies] pytest = "^7.2" diff --git a/tests/cli_tests/test_cli_start.py b/tests/cli_tests/test_cli_start.py index 8045947..819b24f 100644 --- a/tests/cli_tests/test_cli_start.py +++ b/tests/cli_tests/test_cli_start.py @@ -1,6 +1,8 @@ +from textwrap import dedent + +from packaging.version import parse as version_parse # noqa: F401 import pexpect import pytest -from textwrap import dedent def test_start_on_connection_error(): @@ -29,14 +31,14 @@ def test_short_help_option(config): c.close() -@pytest.mark.skipif("int(os.environ['REDIS_VERSION']) != 5") +@pytest.mark.skipif("version_parse(os.environ['REDIS_VERSION']) != version_parse('5')") def test_server_version_in_starting_on5(): c = pexpect.spawn("iredis", timeout=2) c.expect("redis-server 5") c.close() -@pytest.mark.skipif("int(os.environ['REDIS_VERSION']) != 6") +@pytest.mark.skipif("version_parse(os.environ['REDIS_VERSION']) != version_parse('6')") def test_server_version_in_starting_on6(): c = pexpect.spawn("iredis", timeout=2) c.expect("redis-server 6") diff --git a/tests/cli_tests/test_command_input.py b/tests/cli_tests/test_command_input.py index 75917cb..f0aab4a 100644 --- a/tests/cli_tests/test_command_input.py +++ b/tests/cli_tests/test_command_input.py @@ -1,4 +1,6 @@ import os + +from packaging.version import parse as version_parse import pytest @@ -9,7 +11,7 @@ def test_wrong_select_db_index(cli): cli.sendline("select 128") cli.expect(["DB index is out of range", "127.0.0.1:6379[1]>"]) - if int(os.environ["REDIS_VERSION"]) > 5: + if version_parse(os.environ["REDIS_VERSION"]) > version_parse("5"): text = "value is not an integer or out of range" else: text = "invalid DB index" @@ -42,14 +44,14 @@ def test_enter_key_binding(clean_redis, cli): cli.expect(r"hello") -@pytest.mark.skipif("int(os.environ['REDIS_VERSION']) < 6") +@pytest.mark.skipif("version_parse(os.environ['REDIS_VERSION']) < version_parse('6')") def test_auth_hidden_password_with_username(clean_redis, cli): cli.send("auth default hello-world") cli.expect("default") cli.expect(r"\*{11}") -@pytest.mark.skipif("int(os.environ['REDIS_VERSION']) > 5") +@pytest.mark.skipif("version_parse(os.environ['REDIS_VERSION']) > version_parse('5')") def test_auth_hidden_password(clean_redis, cli): cli.send("auth hello-world") cli.expect("auth") diff --git a/tests/cli_tests/test_command_restore.py b/tests/cli_tests/test_command_restore.py new file mode 100644 index 0000000..1c34405 --- /dev/null +++ b/tests/cli_tests/test_command_restore.py @@ -0,0 +1,6 @@ +def test_restore_command(clean_redis, cli): + cli.sendline(r'restore foo1 0 "\x00\x03bar\t\x006L\x18\xac\xba\xe0\x9e\xa6"') + cli.expect(["OK", "127.0.0.1"]) + + cli.sendline("get foo1") + cli.expect('"bar"') diff --git a/tests/cli_tests/test_completer.py b/tests/cli_tests/test_completer.py index 4ffd058..adf8040 100644 --- a/tests/cli_tests/test_completer.py +++ b/tests/cli_tests/test_completer.py @@ -1,3 +1,4 @@ +from packaging.version import parse as version_parse # noqa: F401 import pytest @@ -37,7 +38,7 @@ def test_command_completion_when_space_command(cli, clean_redis): cli.expect("command info") -@pytest.mark.skipif("int(os.environ['REDIS_VERSION']) < 6") +@pytest.mark.skipif("version_parse(os.environ['REDIS_VERSION']) < version_parse('6')") def test_username_completer(cli, iredis_client): iredis_client.execute("acl setuser", "foo1") iredis_client.execute("acl setuser", "bar2") diff --git a/tests/cli_tests/test_pager.py b/tests/cli_tests/test_pager.py index 38ced31..c3f9fb0 100644 --- a/tests/cli_tests/test_pager.py +++ b/tests/cli_tests/test_pager.py @@ -1,10 +1,12 @@ # noqa: F541 +from contextlib import contextmanager import os -import sys -import pexpect import pathlib -from contextlib import contextmanager +import sys from textwrap import dedent +from packaging.version import parse as version_parse + +import pexpect TEST_IREDISRC = "/tmp/.iredisrc.test" @@ -22,6 +24,10 @@ env_pager_numbers = "{0} {1} {2}".format( TEST_PAGER_BOUNDARY_NUMBER, ) +long_list_type = "quicklist" +if version_parse(os.environ["REDIS_VERSION"]) >= version_parse("7"): + long_list_type = "listpack" + @contextmanager def pager_enabled_cli(): @@ -60,7 +66,7 @@ def test_pager_works_for_peek(clean_redis): with pager_enabled_cli() as child: child.sendline("peek long-list") child.expect(TEST_PAGER_BOUNDARY) - child.expect("(quicklist)") + child.expect(f"({long_list_type})") child.expect("value-1") child.expect(TEST_PAGER_BOUNDARY) diff --git a/tests/conftest.py b/tests/conftest.py index b70bf95..593e8a8 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -105,7 +105,7 @@ def cli(): child = pexpect.spawn(f"iredis -n 15 --iredisrc {f.name}", timeout=TIMEOUT, env=env) child.logfile_read = open("cli_test.log", "ab") - child.expect(["https://iredis.io/issues", "127.0.0.1"]) + child.expect(["https://github.com/laixintao/iredis/issues", "127.0.0.1"]) yield child child.close() @@ -129,7 +129,7 @@ def raw_cli(): f"iredis --raw -n 15 --iredisrc {TEST_IREDISRC}", timeout=TIMEOUT ) child.logfile_read = open("cli_test.log", "ab") - child.expect(["https://iredis.io/issues", "127.0.0.1"]) + child.expect(["https://github.com/laixintao/iredis/issues", "127.0.0.1"]) yield child child.close() diff --git a/tests/unittests/test_client.py b/tests/unittests/test_client.py index 45f0054..c0f4c07 100644 --- a/tests/unittests/test_client.py +++ b/tests/unittests/test_client.py @@ -1,18 +1,20 @@ import os import re -import pytest -import redis -from unittest.mock import MagicMock, patch from textwrap import dedent +from unittest.mock import MagicMock, patch +from packaging.version import parse as version_parse from prompt_toolkit.formatted_text import FormattedText +import pytest +import redis from iredis.client import Client -from iredis.config import config, load_config_files +from iredis.commands import command2syntax from iredis.completers import IRedisCompleter +from iredis.config import config, load_config_files from iredis.entry import Rainbow, prompt_message from iredis.exceptions import NotSupport -from iredis.commands import command2syntax + from ..helpers import formatted_text_rematch @@ -22,8 +24,12 @@ def completer(): zset_type = "ziplist" -if os.environ["REDIS_VERSION"] == "7": +hash_type = "hashtable" +list_type = "quicklist" +if version_parse(os.environ["REDIS_VERSION"]) >= version_parse("7"): zset_type = "listpack" + hash_type = "listpack" + list_type = "listpack" @pytest.mark.parametrize( @@ -36,7 +42,7 @@ if os.environ["REDIS_VERSION"] == "7": ], ) def test_send_command(_input, command_name, expect_args): - client = Client("127.0.0.1", "6379", None) + client = Client("127.0.0.1", 6379, None) client.execute = MagicMock() next(client.send_command(_input, None)) args, _ = client.execute.call_args @@ -176,7 +182,7 @@ def test_not_retry_on_authentication_error(iredis_client, config): @pytest.mark.skipif( - "int(os.environ['REDIS_VERSION']) != 6", + "version_parse(os.environ['REDIS_VERSION']) != version_parse('6')", reason=""" in redis7, it will not work if you: 1. connect redis without password @@ -209,7 +215,7 @@ def test_auto_select_db_and_auth_for_reconnect_only_6(iredis_client, config): ) -@pytest.mark.skipif("int(os.environ['REDIS_VERSION']) > 5") +@pytest.mark.skipif("version_parse(os.environ['REDIS_VERSION']) > version_parse('5')") def test_auto_select_db_and_auth_for_reconnect_only_5(iredis_client, config): config.retry_times = 2 config.raw = True @@ -303,7 +309,7 @@ def test_peek_list_fetch_all(iredis_client, clean_redis): FormattedText( [ ("class:dockey", "key: "), - ("", r"list \(quicklist\) mem: \d+ bytes, ttl: -1"), + ("", rf"list \({list_type}\) mem: \d+ bytes, ttl: -1"), ("", "\n"), ("class:dockey", "llen: "), ("", "5"), @@ -351,7 +357,7 @@ def test_peek_set_fetch_part(iredis_client, clean_redis): peek_result = list(iredis_client.do_peek("myset")) assert peek_result[0][0] == ("class:dockey", "key: ") - assert peek_result[0][1][1].startswith("set (hashtable) mem: 2") + assert peek_result[0][1][1].startswith(f"set ({hash_type}) mem: ") def test_peek_zset_fetch_all(iredis_client, clean_redis): @@ -425,7 +431,7 @@ def test_peek_stream(iredis_client, clean_redis): assert peek_result[0][0] == ("class:dockey", "key: ") assert re.match( - r"stream \((stream|unknown)\) mem: 6\d\d bytes, ttl: -1", peek_result[0][1][1] + r"stream \((stream|unknown)\) mem: \d+ bytes, ttl: -1", peek_result[0][1][1] ) assert peek_result[0][2:18] == FormattedText( [ @@ -550,23 +556,29 @@ def test_version_parse_for_auth(iredis_client): "info, version", [ ( - "# Server\r\nredis_version:df--128-NOTFOUND\r\n" - "redis_mode:standalone\r\narch_bits:64", + ( + "# Server\r\nredis_version:df--128-NOTFOUND\r\n" + "redis_mode:standalone\r\narch_bits:64" + ), "df--128-NOTFOUND", ), ( - "# Server\r\nredis_version:6.2.5\r\n" - "redis_git_sha1:00000000\r\n" - "redis_git_dirty:0\r\n" - "redis_build_id:915e5480613bc9b6\r\n" - "redis_mode:standalone ", + ( + "# Server\r\nredis_version:6.2.5\r\n" + "redis_git_sha1:00000000\r\n" + "redis_git_dirty:0\r\n" + "redis_build_id:915e5480613bc9b6\r\n" + "redis_mode:standalone " + ), "6.2.5", ), ( - "# Server\r\nredis_version:5.0.14.1\r\n" - "redis_git_sha1:00000000\r\nredis_git_dirty:0\r\n" - "redis_build_id:915e5480613bc9b6\r\n" - "redis_mode:standalone ", + ( + "# Server\r\nredis_version:5.0.14.1\r\n" + "redis_git_sha1:00000000\r\nredis_git_dirty:0\r\n" + "redis_build_id:915e5480613bc9b6\r\n" + "redis_mode:standalone " + ), "5.0.14.1", ), ], @@ -576,9 +588,10 @@ def test_version_path(info, version): mock_config.no_info = True mock_config.pager = "less" mock_config.version = "5.0.0" + mock_config.decode = "utf-8" with patch("iredis.client.Client.execute") as mock_execute: mock_execute.return_value = info - client = Client("127.0.0.1", "6379", None) + client = Client("127.0.0.1", 6379) client.get_server_info() assert mock_config.version == version diff --git a/tests/unittests/test_entry.py b/tests/unittests/test_entry.py index 912aabf..e53861e 100644 --- a/tests/unittests/test_entry.py +++ b/tests/unittests/test_entry.py @@ -28,7 +28,6 @@ from iredis.utils import DSN def test_command_entry_tty(is_tty, raw_arg_is_raw, final_config_is_raw, config): # is tty + raw -> raw with patch("sys.stdout.isatty") as patch_tty: - patch_tty.return_value = is_tty if raw_arg_is_raw is None: call = ["iredis"] diff --git a/tests/unittests/test_markdown_doc_render.py b/tests/unittests/test_markdown_doc_render.py index 0538299..0c66260 100644 --- a/tests/unittests/test_markdown_doc_render.py +++ b/tests/unittests/test_markdown_doc_render.py @@ -6,7 +6,7 @@ https://github.com/antirez/redis-doc/commit/02b3d1a345093c1794fd86273e9d516fffd3 """ import pytest -from importlib_resources import read_text +from importlib.resources import read_text from iredis.commands import commands_summary from iredis.data import commands as commands_data -- cgit v1.2.3