From 8a5993625f12176cf32937f60770a87bf59f343a Mon Sep 17 00:00:00 2001 From: 40handz Date: Tue, 17 Mar 2026 17:03:33 -0400 Subject: [PATCH 1/5] Bump Python 3.10+ dependencies to resolve known vulnerabilities (v3.3.4) - cryptography: 41.0.0 -> 46.0.5 - requests: 2.27.1 -> 2.32.4 - urllib3: 1.26.9 -> 2.6.3 (major version bump, tested compatible) - aiohttp: 3.8.1 -> 3.13.3 - pynacl: 1.5.0 -> 1.6.2 - Updated transitive deps: aiosignal, async-timeout, attrs, certifi, charset-normalizer, frozenlist, idna, multidict, propcache, pycparser, six, yarl Python < 3.10 pinned versions unchanged. --- CHANGELOG.md | 8 ++++++-- pusher/version.py | 2 +- requirements.txt | 35 ++++++++++++++++++----------------- 3 files changed, 25 insertions(+), 20 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4a565b0..3c2a176 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,12 +1,16 @@ # Changelog +## 3.3.4 + +- [FIXED] Bump Python 3.10+ dependencies to resolve known vulnerabilities: cryptography (41.0.0 → 46.0.5), requests (2.27.1 → 2.32.4), urllib3 (1.26.9 → 2.6.3), aiohttp (3.8.1 → 3.13.3), pynacl (1.5.0 → 1.6.2) + ## 3.3.2 -- [CHANGED] Utilities no longer escape non ascii characters. +- [CHANGED] Utilities no longer escape non ascii characters. ## 3.3.1 -- [ADDED] Allow Client to accept float as a timeout +- [ADDED] Allow Client to accept float as a timeout - [CHANGED] the maximum event payload size permitted by this library has been increased. This change affects the library only: the Channels API still maintains a 10kb size limit and will return an error if the payload is too large. ## 3.3.0 diff --git a/pusher/version.py b/pusher/version.py index 3613411..b64ede1 100644 --- a/pusher/version.py +++ b/pusher/version.py @@ -1,2 +1,2 @@ # Don't change the format of this line: the version is extracted by ../setup.py -VERSION = '3.3.3' +VERSION = '3.3.4' diff --git a/requirements.txt b/requirements.txt index 852ba03..0235758 100644 --- a/requirements.txt +++ b/requirements.txt @@ -16,30 +16,31 @@ pyOpenSSL==19.0.0; python_version < '3.10' requests==2.22.0; python_version < '3.10' six==1.12.0; python_version < '3.10' urllib3==1.25.9; python_version < '3.10' -aiohttp==3.5.4; python_version >= '3.5' and python_version < '3.10' -aiohttp==3.8.1; python_version >= '3.10' -aiosignal==1.2.0; python_version >= '3.10' +aiohappyeyeballs==2.6.1; python_version >= '3.10' +aiohttp==3.13.3; python_version >= '3.10' +aiosignal==1.4.0; python_version >= '3.10' async-timeout==3.0.1; python_version >= '3.5' and python_version < '3.10' -async-timeout==4.0.2; python_version >= '3.10' +async-timeout==5.0.1; python_version >= '3.10' attrs==19.1.0; python_version >= '3.5' and python_version < '3.10' -attrs==21.4.0; python_version >= '3.10' -certifi==2021.10.8; python_version >= '3.10' -charset-normalizer==2.0.12; python_version >= '3.10' -cryptography==41.0.0; python_version >= '3.10' -frozenlist==1.3.0; python_version >= '3.10' +attrs==25.4.0; python_version >= '3.10' +certifi==2026.2.25; python_version >= '3.10' +charset-normalizer==3.4.6; python_version >= '3.10' +cryptography==46.0.5; python_version >= '3.10' +frozenlist==1.8.0; python_version >= '3.10' httpretty==1.1.4; python_version >= '3.10' idna-ssl==1.1.0; python_version >= '3.5' and python_version < '3.7' -idna==3.3; python_version >= '3.10' +idna==3.11; python_version >= '3.10' multidict==4.5.2; python_version >= '3.5' and python_version < '3.10' -multidict==6.0.2; python_version >= '3.10' +multidict==6.7.1; python_version >= '3.10' +propcache==0.4.1; python_version >= '3.10' py==1.11.0; python_version >= '3.10' -pycparser==2.21; python_version >= '3.10' -PyNaCl==1.5.0; python_version >= '3.10' +pycparser==2.23; python_version >= '3.10' +PyNaCl==1.6.2; python_version >= '3.10' pyparsing==3.0.8; python_version >= '3.10' -requests==2.27.1; python_version >= '3.10' -six==1.16.0; python_version >= '3.10' +requests==2.32.4; python_version >= '3.10' +six==1.17.0; python_version >= '3.10' tornado==5.1.1; python_version < '3.5' tornado==6.0.2; python_version >= '3.5' and python_version < '3.10' -urllib3==1.26.9; python_version >= '3.10' +urllib3==2.6.3; python_version >= '3.10' yarl==1.3.0; python_version >= '3.5' and python_version < '3.10' -yarl==1.7.2; python_version >= '3.10' +yarl==1.22.0; python_version >= '3.10' From cfb4e2e343a77627ef1223b6f86be02507af4025 Mon Sep 17 00:00:00 2001 From: 40handz Date: Wed, 18 Mar 2026 15:08:05 -0400 Subject: [PATCH 2/5] ci: update test workflow to ubuntu-latest, Python 3.10-3.12, modern test command ubuntu-20.04 runners were retired from GitHub Actions, causing jobs to be permanently stuck in queued state. Python 3.6, 3.7, and 3.8 are EOL and have unfixed vulnerabilities in the locked deps. Updated to currently supported Python versions (3.10, 3.11, 3.12) which align with the 3.10+ dependency bumps in this PR. Replaced deprecated 'python setup.py test' with 'python -m unittest discover' since setup.py test was removed in modern setuptools. --- .github/workflows/test.yml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 5892c57..fbcb79a 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -7,20 +7,20 @@ on: jobs: test: - runs-on: ubuntu-20.04 + runs-on: ubuntu-latest strategy: fail-fast: false matrix: - python: [3.6, 3.7, 3.8, "3.10"] + python: ["3.10", "3.11", "3.12"] name: Python ${{ matrix.python }} Test steps: - name: Checkout - uses: actions/checkout@v2 + uses: actions/checkout@v4 - name: Setup Python - uses: actions/setup-python@v2 + uses: actions/setup-python@v5 with: python-version: ${{ matrix.python }} @@ -28,4 +28,4 @@ jobs: run: pip install -r requirements.txt - name: Run test suite - run: python setup.py test + run: python -m unittest discover -s pusher_tests From 0ba7f5904f597fe418d291483a02a89ad5ca61b4 Mon Sep 17 00:00:00 2001 From: 40handz Date: Wed, 18 Mar 2026 15:09:12 -0400 Subject: [PATCH 3/5] ci: fix unittest discover to use top-level-directory for package imports The test_aiohttp_adapter module uses a relative import (.aio.aiohttp_adapter_test). Without --top-level-directory ., unittest discover imports test files as top-level modules rather than as members of the pusher_tests package, breaking relative imports. --- .github/workflows/test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index fbcb79a..bb20fab 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -28,4 +28,4 @@ jobs: run: pip install -r requirements.txt - name: Run test suite - run: python -m unittest discover -s pusher_tests + run: python -m unittest discover -s pusher_tests --top-level-directory . From 7d3183f7ccf3bdcadb04c13b1b1ba41eb7943db2 Mon Sep 17 00:00:00 2001 From: 40handz Date: Wed, 18 Mar 2026 15:10:42 -0400 Subject: [PATCH 4/5] fix: replace deprecated asyncio.coroutine with async/await in aiohttp backend asyncio.coroutine was removed in Python 3.11. Convert to native async/await syntax which has been supported since Python 3.5. --- pusher/aiohttp.py | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/pusher/aiohttp.py b/pusher/aiohttp.py index 12cd870..7d6befe 100644 --- a/pusher/aiohttp.py +++ b/pusher/aiohttp.py @@ -7,7 +7,6 @@ division) import aiohttp -import asyncio from pusher.http import process_response @@ -21,12 +20,11 @@ def __init__(self, client): self.client = client - @asyncio.coroutine - def send_request(self, request): + async def send_request(self, request): session = response = None try: session = aiohttp.ClientSession() - response = yield from session.request( + response = await session.request( request.method, "%s%s" % (request.base_url, request.path), params=request.query_params, @@ -34,10 +32,10 @@ def send_request(self, request): headers=request.headers, timeout=self.client.timeout ) - body = yield from response.text('utf-8') + body = await response.text('utf-8') return process_response(response.status, body) finally: if response is not None: response.close() if session is not None: - yield from session.close() + await session.close() From 4b6101ff1c697159204d6607e2bc078138229164 Mon Sep 17 00:00:00 2001 From: 40handz Date: Thu, 19 Mar 2026 10:32:23 -0400 Subject: [PATCH 5/5] Update deprecated GitHub Actions in workflows --- .github/workflows/release.yml | 18 +++++++++--------- .github/workflows/release_pr.yml | 4 ++-- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index eaa6a64..0ba1633 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -7,7 +7,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout code - uses: actions/checkout@v2 + uses: actions/checkout@v4 with: fetch-depth: 0 - name: Prepare tag @@ -26,7 +26,7 @@ jobs: id: release_output if: ${{ steps.prepare_tag.outcome == 'success' }} run: | - echo "::set-output name=tag::${{ env.TAG }}" + echo "tag=${{ env.TAG }}" >> $GITHUB_OUTPUT outputs: tag: ${{ steps.release_output.outputs.tag }} @@ -35,7 +35,7 @@ jobs: needs: check-release-tag if: ${{ needs.check-release-tag.outputs.tag }} steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - name: Prepare tag run: | export TAG=v$(awk '/VERSION =/ { gsub("'"\'"'",""); print $3 }' pusher/version.py) @@ -49,22 +49,22 @@ jobs: csplit -s CHANGELOG.md "/##/" {1} cat xx01 > CHANGELOG.tmp - name: Create Release - uses: actions/create-release@v1 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + uses: softprops/action-gh-release@v2.6.1 with: tag_name: ${{ env.TAG }} - release_name: ${{ env.TAG }} + name: ${{ env.TAG }} body_path: CHANGELOG.tmp draft: false prerelease: false + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} upload-to-PyPI: runs-on: ubuntu-latest needs: create-github-release steps: - - uses: actions/checkout@v2 - - uses: actions/setup-python@v4 + - uses: actions/checkout@v4 + - uses: actions/setup-python@v5 with: python-version: '3.10' - name: Build package diff --git a/.github/workflows/release_pr.yml b/.github/workflows/release_pr.yml index 191cb25..83a3e30 100644 --- a/.github/workflows/release_pr.yml +++ b/.github/workflows/release_pr.yml @@ -11,13 +11,13 @@ jobs: name: Prepare release runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - name: Get current version shell: bash run: | CURRENT_VERSION=$(awk '/VERSION =/ { gsub("'"\'"'",""); print $3 }' pusher/version.py) echo "CURRENT_VERSION=$CURRENT_VERSION" >> $GITHUB_ENV - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 with: repository: pusher/public_actions path: .github/actions