summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDaniel Baumann <mail@daniel-baumann.ch>2023-11-04 18:52:12 +0000
committerDaniel Baumann <mail@daniel-baumann.ch>2023-11-04 18:52:12 +0000
commita596894f2d782b9df54c026696e55da1267f7936 (patch)
treee2696ad38feb91700ac875966e6aa0b30e732566
parentAdding upstream version 1.13.1. (diff)
downloadiredis-a596894f2d782b9df54c026696e55da1267f7936.tar.xz
iredis-a596894f2d782b9df54c026696e55da1267f7936.zip
Adding upstream version 1.14.0.upstream/1.14.0
Signed-off-by: Daniel Baumann <mail@daniel-baumann.ch>
-rw-r--r--.bumpversion.cfg2
-rw-r--r--.dockerignore7
-rw-r--r--.github/workflows/test.yaml3
-rw-r--r--CHANGELOG.md31
-rw-r--r--Dockerfile28
-rw-r--r--README.md4
-rw-r--r--iredis/__init__.py2
-rw-r--r--iredis/client.py11
-rw-r--r--iredis/commands.py2
-rw-r--r--iredis/completers.py1
-rw-r--r--iredis/config.py5
-rw-r--r--iredis/data/iredisrc4
-rw-r--r--iredis/entry.py22
-rw-r--r--iredis/markdown.py4
-rw-r--r--poetry.lock387
-rw-r--r--pyproject.toml16
-rw-r--r--tests/cli_tests/test_cli_start.py8
-rw-r--r--tests/cli_tests/test_command_input.py8
-rw-r--r--tests/cli_tests/test_command_restore.py6
-rw-r--r--tests/cli_tests/test_completer.py3
-rw-r--r--tests/cli_tests/test_pager.py14
-rw-r--r--tests/conftest.py4
-rw-r--r--tests/unittests/test_client.py61
-rw-r--r--tests/unittests/test_entry.py1
-rw-r--r--tests/unittests/test_markdown_doc_render.py2
25 files changed, 319 insertions, 317 deletions
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=<none|optional|required>`) 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=<none|optional|required>`) 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 @@
<p align="center">
<a href="https://github.com/laixintao/iredis/actions"><img src="https://github.com/laixintao/iredis/workflows/Test/badge.svg" alt="Github Action"></a>
<a href="https://badge.fury.io/py/iredis"><img src="https://badge.fury.io/py/iredis.svg" alt="PyPI version"></a>
-<img src="https://badgen.net/badge/python/3.6%20%7C%203.7%20%7C%203.8%20%7C%203.9%20%7C%203.10/" alt="Python version">
+<img src="https://badgen.net/badge/python/3.7%20%7C%203.8%20%7C%203.9%20%7C%203.10%20%7C%203.11" alt="Python version">
<a href="https://pepy.tech/project/iredis"><img src="https://pepy.tech/badge/iredis" alt="Download stats"></a>
</p>
@@ -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(),
@@ -275,6 +275,12 @@ VERIFY_SSL_HELP = """Set the TLS certificate verification strategy"""
@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,
type=click.Choice(["none", "optional", "required"]),
@@ -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 ``<ul>`` and ``<ol>``.
:param body: body contents of the list.
@@ -41,7 +41,7 @@ class TerminalRender(mistune.HTMLRenderer):
tag = "ol"
return "<%s>%s</%s>\n" % (tag, body, tag)
- def list_item(self, text, level):
+ def list_item(self, text, *args):
"""Rendering list item snippet. Like ``<li>``."""
return "<li> * %s</li>\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 <laixintao1995@163.com>"]
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