diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS new file mode 100644 index 0000000000..1af2323fe9 --- /dev/null +++ b/.github/CODEOWNERS @@ -0,0 +1 @@ +doctests/* @dmaier-redislabs diff --git a/.github/release-drafter-config.yml b/.github/release-drafter-config.yml index 9ccb28aca4..4607da071c 100644 --- a/.github/release-drafter-config.yml +++ b/.github/release-drafter-config.yml @@ -1,5 +1,7 @@ name-template: '$NEXT_MINOR_VERSION' tag-template: 'v$NEXT_MINOR_VERSION' +filter-by-commitish: true +commitish: master autolabeler: - label: 'maintenance' files: @@ -15,7 +17,7 @@ autolabeler: branch: - '/feature-.+' categories: - - title: 'Breaking Changes' + - title: '🔥 Breaking Changes' labels: - 'breakingchange' - title: '🧪 Experimental Features' @@ -32,7 +34,12 @@ categories: - 'bug' - 'BUG' - title: '🧰 Maintenance' - label: 'maintenance' + labels: + - 'maintenance' + - 'dependencies' + - 'documentation' + - 'docs' + - 'testing' change-template: '- $TITLE (#$NUMBER)' exclude-labels: - 'skip-changelog' diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index e82e7e1530..4670c55b0f 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -36,11 +36,11 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@v3 + uses: actions/checkout@v4 # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@v2 + uses: github/codeql-action/init@v3 with: languages: ${{ matrix.language }} # If you wish to specify custom queries, you can do so here or in a config file. @@ -51,7 +51,7 @@ jobs: # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). # If this step fails, then you should remove it and run the build manually (see below) - name: Autobuild - uses: github/codeql-action/autobuild@v2 + uses: github/codeql-action/autobuild@v3 # ℹ️ Command-line programs to run using the OS shell. # 📚 https://git.io/JvXDl @@ -65,4 +65,4 @@ jobs: # make release - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@v2 + uses: github/codeql-action/analyze@v3 diff --git a/.github/workflows/docs.yaml b/.github/workflows/docs.yaml index 61ec76e9f8..c5c74aa4d3 100644 --- a/.github/workflows/docs.yaml +++ b/.github/workflows/docs.yaml @@ -25,8 +25,8 @@ jobs: name: Build docs runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 - - uses: actions/setup-python@v4 + - uses: actions/checkout@v4 + - uses: actions/setup-python@v5 with: python-version: 3.9 cache: 'pip' @@ -40,7 +40,7 @@ jobs: invoke build-docs - name: upload docs - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: redis-py-docs path: | diff --git a/.github/workflows/integration.yaml b/.github/workflows/integration.yaml index 7e0fea2e41..584999d8e7 100644 --- a/.github/workflows/integration.yaml +++ b/.github/workflows/integration.yaml @@ -29,7 +29,7 @@ jobs: name: Dependency audit runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - uses: pypa/gh-action-pip-audit@v1.0.8 with: inputs: requirements.txt dev_requirements.txt @@ -40,8 +40,8 @@ jobs: name: Code linters runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 - - uses: actions/setup-python@v4 + - uses: actions/checkout@v4 + - uses: actions/setup-python@v5 with: python-version: 3.9 cache: 'pip' @@ -64,8 +64,8 @@ jobs: ACTIONS_ALLOW_UNSECURE_COMMANDS: true name: Python ${{ matrix.python-version }} ${{matrix.test-type}}-${{matrix.connection-type}} tests steps: - - uses: actions/checkout@v3 - - uses: actions/setup-python@v4 + - uses: actions/checkout@v4 + - uses: actions/setup-python@v5 with: python-version: ${{ matrix.python-version }} cache: 'pip' @@ -81,15 +81,14 @@ jobs: sleep 10 # time to settle invoke ${{matrix.test-type}}-tests - - uses: actions/upload-artifact@v3 + - uses: actions/upload-artifact@v4 if: success() || failure() with: name: pytest-results-${{matrix.test-type}}-${{matrix.connection-type}}-${{matrix.python-version}} path: '${{matrix.test-type}}*results.xml' - name: Upload codecov coverage - uses: codecov/codecov-action@v3 - if: ${{matrix.python-version == '3.11'}} + uses: codecov/codecov-action@v4 with: fail_ci_if_error: false @@ -119,8 +118,8 @@ jobs: ACTIONS_ALLOW_UNSECURE_COMMANDS: true name: RESP3 [${{ matrix.python-version }} ${{matrix.test-type}}-${{matrix.connection-type}}] steps: - - uses: actions/checkout@v3 - - uses: actions/setup-python@v4 + - uses: actions/checkout@v4 + - uses: actions/setup-python@v5 with: python-version: ${{ matrix.python-version }} cache: 'pip' @@ -146,8 +145,8 @@ jobs: matrix: extension: ['tar.gz', 'whl'] steps: - - uses: actions/checkout@v3 - - uses: actions/setup-python@v4 + - uses: actions/checkout@v4 + - uses: actions/setup-python@v5 with: python-version: 3.9 - name: Run installed unit tests @@ -162,8 +161,8 @@ jobs: matrix: python-version: ['3.7', '3.8', '3.9', '3.10', '3.11', 'pypy-3.7', 'pypy-3.8', 'pypy-3.9'] steps: - - uses: actions/checkout@v3 - - uses: actions/setup-python@v4 + - uses: actions/checkout@v4 + - uses: actions/setup-python@v5 with: python-version: ${{ matrix.python-version }} cache: 'pip' diff --git a/.github/workflows/pypi-publish.yaml b/.github/workflows/pypi-publish.yaml index 50332c1995..30720d7b8a 100644 --- a/.github/workflows/pypi-publish.yaml +++ b/.github/workflows/pypi-publish.yaml @@ -12,9 +12,9 @@ jobs: build_and_package: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: install python - uses: actions/setup-python@v4 + uses: actions/setup-python@v5 with: python-version: 3.9 - name: Install dev tools diff --git a/.github/workflows/spellcheck.yml b/.github/workflows/spellcheck.yml index e152841553..a48781aa84 100644 --- a/.github/workflows/spellcheck.yml +++ b/.github/workflows/spellcheck.yml @@ -6,9 +6,9 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Check Spelling - uses: rojopolis/spellcheck-github-actions@0.33.1 + uses: rojopolis/spellcheck-github-actions@0.35.0 with: config_path: .github/spellcheck-settings.yml task_name: Markdown diff --git a/CHANGES b/CHANGES index 8cfc47db18..f0e90fc16e 100644 --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,8 @@ + * Allow to control the minimum SSL version + * Add an optional lock_name attribute to LockError. + * Fix return types for `get`, `set_path` and `strappend` in JSONCommands + * Connection.register_connect_callback() is made public. + * Fix async `read_response` to use `disable_decoding`. * Add 'aclose()' methods to async classes, deprecate async close(). * Fix #2831, add auto_close_connection_pool=True arg to asyncio.Redis.from_url() * Fix incorrect redis.asyncio.Cluster type hint for `retry_on_error` @@ -55,6 +60,7 @@ * Fix for Unhandled exception related to self.host with unix socket (#2496) * Improve error output for master discovery * Make `ClusterCommandsProtocol` an actual Protocol + * Add `sum` to DUPLICATE_POLICY documentation of `TS.CREATE`, `TS.ADD` and `TS.ALTER` * 4.1.3 (Feb 8, 2022) * Fix flushdb and flushall (#1926) diff --git a/README.md b/README.md index 4bd71b4060..2097e87bba 100644 --- a/README.md +++ b/README.md @@ -17,6 +17,20 @@ The Python interface to the Redis key-value store. --------------------------------------------- +## How do I Redis? + +[Learn for free at Redis University](https://university.redis.com/) + +[Build faster with the Redis Launchpad](https://launchpad.redis.com/) + +[Try the Redis Cloud](https://redis.com/try-free/) + +[Dive in developer tutorials](https://developer.redis.com/) + +[Join the Redis community](https://redis.com/community/) + +[Work at Redis](https://redis.com/company/careers/jobs/) + ## Installation Start a redis via docker: diff --git a/docs/advanced_features.rst b/docs/advanced_features.rst index fd29d2f684..de645bd764 100644 --- a/docs/advanced_features.rst +++ b/docs/advanced_features.rst @@ -346,7 +346,7 @@ running. The third option runs an event loop in a separate thread. pubsub.run_in_thread() creates a new thread and starts the event loop. -The thread object is returned to the caller of [un_in_thread(). The +The thread object is returned to the caller of run_in_thread(). The caller can use the thread.stop() method to shut down the event loop and thread. Behind the scenes, this is simply a wrapper around get_message() that runs in a separate thread, essentially creating a tiny non-blocking diff --git a/docs/clustering.rst b/docs/clustering.rst index 9b4dee1c9f..f8320e4e59 100644 --- a/docs/clustering.rst +++ b/docs/clustering.rst @@ -92,7 +92,7 @@ The ‘target_nodes’ parameter is explained in the following section, >>> # target-node: default-node >>> rc.ping() -Specfiying Target Nodes +Specifying Target Nodes ----------------------- As mentioned above, all non key-based RedisCluster commands accept the diff --git a/docs/conf.py b/docs/conf.py index 8849752404..a201da2fc0 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -86,7 +86,7 @@ # List of patterns, relative to source directory, that match files and # directories to ignore when looking for source files. -exclude_patterns = ["_build", "**.ipynb_checkponts"] +exclude_patterns = ["_build", "**.ipynb_checkpoints"] # The reST default role (used for this markup: `text`) to use for all # documents. diff --git a/docs/examples/asyncio_examples.ipynb b/docs/examples/asyncio_examples.ipynb index 5eab4db1f7..5029e907da 100644 --- a/docs/examples/asyncio_examples.ipynb +++ b/docs/examples/asyncio_examples.ipynb @@ -201,7 +201,7 @@ "\n", "async def reader(channel: redis.client.PubSub):\n", " while True:\n", - " message = await channel.get_message(ignore_subscribe_messages=True)\n", + " message = await channel.get_message(ignore_subscribe_messages=True, timeout=None)\n", " if message is not None:\n", " print(f\"(Reader) Message Received: {message}\")\n", " if message[\"data\"].decode() == STOPWORD:\n", @@ -264,7 +264,7 @@ "\n", "async def reader(channel: redis.client.PubSub):\n", " while True:\n", - " message = await channel.get_message(ignore_subscribe_messages=True)\n", + " message = await channel.get_message(ignore_subscribe_messages=True, timeout=None)\n", " if message is not None:\n", " print(f\"(Reader) Message Received: {message}\")\n", " if message[\"data\"].decode() == STOPWORD:\n", diff --git a/docs/examples/pipeline_examples.ipynb b/docs/examples/pipeline_examples.ipynb index 4e20375bfa..36ce31d708 100644 --- a/docs/examples/pipeline_examples.ipynb +++ b/docs/examples/pipeline_examples.ipynb @@ -123,7 +123,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "The responses of the three commands are stored in a list. In the above example, the two first boolean indicates that the `set` commands were successfull and the last element of the list is the result of the `get(\"a\")` comand." + "The responses of the three commands are stored in a list. In the above example, the two first boolean indicates that the `set` commands were successful and the last element of the list is the result of the `get(\"a\")` comand." ] }, { diff --git a/docs/examples/ssl_connection_examples.ipynb b/docs/examples/ssl_connection_examples.ipynb index ab3b4415ae..a3d015619f 100644 --- a/docs/examples/ssl_connection_examples.ipynb +++ b/docs/examples/ssl_connection_examples.ipynb @@ -76,6 +76,42 @@ "ssl_connection.ping()" ] }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Connecting to a Redis instance via SSL, while specifying a minimum TLS version" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "True" + ] + }, + "execution_count": 6, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "import redis\n", + "import ssl\n", + "\n", + "ssl_conn = redis.Redis(\n", + " host=\"localhost\",\n", + " port=6666,\n", + " ssl=True,\n", + " ssl_min_version=ssl.TLSVersion.TLSv1_3,\n", + ")\n", + "ssl_conn.ping()" + ] + }, { "cell_type": "markdown", "metadata": {}, diff --git a/docs/lua_scripting.rst b/docs/lua_scripting.rst index 0edb6b6723..bd7b9bc01d 100644 --- a/docs/lua_scripting.rst +++ b/docs/lua_scripting.rst @@ -92,19 +92,24 @@ Cluster Mode Cluster mode has limited support for lua scripting. -The following commands are supported, with caveats: - ``EVAL`` and -``EVALSHA``: The command is sent to the relevant node, depending on the -keys (i.e., in ``EVAL "