From bdf5d3e29ae24269c0242f1aac540b1a07f455b9 Mon Sep 17 00:00:00 2001 From: Michael Marchetti Date: Wed, 4 Jan 2023 11:21:49 -0500 Subject: [PATCH 1/5] stop testing 3.5 and 3.6 --- .github/workflows/main.yml | 8 +++----- CONTRIBUTING.md | 2 +- Makefile | 10 ++-------- 3 files changed, 6 insertions(+), 14 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index effacf5c..7fe9bd24 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -14,7 +14,7 @@ jobs: matrix: # TODO: work on windows-latest compatibility? os: [ubuntu-latest] - python-version: ['3.5', '3.6', '3.7', '3.8', '3.9', '3.10'] + python-version: ['3.7', '3.8', '3.9', '3.10'] include: - os: macos-latest python-version: '3.9' @@ -28,10 +28,8 @@ jobs: python-version: ${{ matrix.python-version }} - run: pip install -r requirements.txt - run: pip freeze - - if: matrix.python-version > '3.5' - run: make fmt - - if: matrix.python-version >= '3.6' - run: make lint + - run: make fmt + - run: make lint - run: python setup.py --version - run: make test-${{ matrix.python-version }} prerelease-test: diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index f6277b0c..832c5251 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -5,7 +5,7 @@ tooling](https://packaging.python.org/guides/tool-recommendations/). To get started, you'll want to: - clone the repo into a project directory -- setup a virtual 3.5+ python environment in the project directory +- setup a virtual 3.7+ python environment in the project directory - activate that virtual environment - install the dependencies - validate your build environment with some sample commands diff --git a/Makefile b/Makefile index e4563d62..1d24b833 100644 --- a/Makefile +++ b/Makefile @@ -35,10 +35,10 @@ SOURCE_DATE_EPOCH := $(shell date +%s) export SOURCE_DATE_EPOCH .PHONY: all-tests -all-tests: all-images test-3.5 test-3.6 test-3.7 test-3.8 test-3.9 test-3.10 +all-tests: all-images test-3.7 test-3.8 test-3.9 test-3.10 .PHONY: all-images -all-images: image-3.5 image-3.6 image-3.7 image-3.8 image-3.9 image-3.10 +all-images: image-3.7 image-3.8 image-3.9 image-3.10 image-%: docker build -t rsconnect-python:$* --build-arg BASE_IMAGE=python:$*-slim . @@ -62,9 +62,6 @@ mock-test-%: clean-stores fmt-%: $(RUNNER) 'black .' -.PHONY: fmt-3.5 -fmt-3.5: .fmt-unsupported - .PHONY: .fmt-unsupported .fmt-unsupported: @echo ERROR: This python version cannot run the fmting tools @@ -83,9 +80,6 @@ lint-%: $(RUNNER) 'flake8 tests/' $(RUNNER) 'mypy -p rsconnect' -.PHONY: lint-3.5 -lint-3.5: .lint-unsupported - .PHONY: .lint-unsupported .lint-unsupported: @echo ERROR: This python version cannot run the linting tools From 20960aff470e22f893d1f57e1ca8b03b4a2ec032 Mon Sep 17 00:00:00 2001 From: Michael Marchetti Date: Wed, 4 Jan 2023 11:22:37 -0500 Subject: [PATCH 2/5] remove old dependencies --- requirements.txt | 9 ++++----- setup.cfg | 5 ++--- 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/requirements.txt b/requirements.txt index 0712b0ca..75c7e18b 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,4 +1,4 @@ -black==22.3.0; python_version >= '3.6' +black==22.3.0 click>=7.0.0 coverage flake8 @@ -8,13 +8,12 @@ importlib-metadata ipykernel ipython jupyter_client -mypy; python_version >= '3.6' +mypy nbconvert -pyjwt>=2.4.0; python_version >= '3.6' -pyjwt; python_version < '3.6' +pyjwt>=2.4.0 pytest pytest-cov -pytest-mypy; python_version >= '3.5' +pytest-mypy semver>=2.0.0,<3.0.0 setuptools_scm six>=1.14.0 diff --git a/setup.cfg b/setup.cfg index d65eca7c..876b73ee 100644 --- a/setup.cfg +++ b/setup.cfg @@ -20,15 +20,14 @@ install_requires = click>=7.0.0 pip>=10.0.0 semver>=2.0.0,<3.0.0 - pyjwt>=2.4.0; python_version >= '3.6' - pyjwt; python_version < '3.6' + pyjwt>=2.4.0 setup_requires = setuptools setuptools_scm>=3.4 toml wheel packages = rsconnect -python_requires = >=3.5 +python_requires = >=3.7 zip_safe = true [options.entry_points] From eb3ab5d14999afd044dc754e68ef82ce40c4be63 Mon Sep 17 00:00:00 2001 From: Michael Marchetti Date: Wed, 4 Jan 2023 11:22:48 -0500 Subject: [PATCH 3/5] update release notes --- README.md | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/README.md b/README.md index ba63ce31..46e61f9e 100644 --- a/README.md +++ b/README.md @@ -2,9 +2,7 @@ !!! warning - As of version 1.7.0, rsconnect-python requires Python version 3.5 or higher. Please see the - [official announcement](https://www.rstudio.com/blog/rstudio-connect-2021-08-python-updates/) - for details about this decision. + As of version 1.14.0, rsconnect-python requires Python version 3.7 or higher. This package provides a CLI (command-line interface) for interacting with and deploying to Posit Connect. This is also used by the From a7557844622cf6ec024f65c5a37ecfd3c945e39d Mon Sep 17 00:00:00 2001 From: Michael Marchetti Date: Wed, 4 Jan 2023 11:23:06 -0500 Subject: [PATCH 4/5] remove is_jwt_compatible_python_version checks --- rsconnect/json_web_token.py | 9 --------- rsconnect/main.py | 6 ------ tests/test_json_web_token.py | 11 ----------- tests/test_main.py | 5 +---- tests/test_utils.py | 6 ------ 5 files changed, 1 insertion(+), 36 deletions(-) diff --git a/rsconnect/json_web_token.py b/rsconnect/json_web_token.py index 72e846de..e0814093 100644 --- a/rsconnect/json_web_token.py +++ b/rsconnect/json_web_token.py @@ -5,7 +5,6 @@ import base64 from datetime import datetime, timedelta, timezone import os -import sys import binascii import jwt @@ -64,14 +63,6 @@ def validate_hs256_secret_key(key: bytes): raise RSConnectException("Secret key expected to be at least 32 bytes in length") -def is_jwt_compatible_python_version() -> bool: - """ - JWT library is incompatible with Python 3.5 - """ - - return not sys.version_info < (3, 6) - - def parse_client_response(response): """ Helper to handle the response type from RSConnectClient, because diff --git a/rsconnect/main.py b/rsconnect/main.py index 9a5c5946..b9dab584 100644 --- a/rsconnect/main.py +++ b/rsconnect/main.py @@ -71,7 +71,6 @@ from .json_web_token import ( read_secret_key, validate_hs256_secret_key, - is_jwt_compatible_python_version, TokenGenerator, produce_bootstrap_output, parse_client_response, @@ -333,11 +332,6 @@ def bootstrap( verbose, ): set_verbosity(verbose) - if not is_jwt_compatible_python_version(): - raise RSConnectException( - "Python version > 3.5 required for JWT generation. Please upgrade your Python installation." - ) - if not server.startswith("http"): raise RSConnectException("Server URL expected to begin with transfer protocol (ex. http/https).") diff --git a/tests/test_json_web_token.py b/tests/test_json_web_token.py index 0efdf155..662358f5 100644 --- a/tests/test_json_web_token.py +++ b/tests/test_json_web_token.py @@ -18,7 +18,6 @@ SECRET_KEY_ENV, read_secret_key, produce_bootstrap_output, - is_jwt_compatible_python_version, parse_client_response, TokenGenerator, JWTEncoder, @@ -43,9 +42,6 @@ def are_unix_timestamps_approx_equal(a, b): class TestJsonWebToken(TestCase): def setUp(self): - if not is_jwt_compatible_python_version(): - self.skipTest("JWTs not supported in Python < 3.6") - # decoded copy of the base64-encoded key in testdata/jwt/secret.key self.secret_key = b"12345678901234567890123456789012345" self.secret_key_b64 = b"MTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU=" @@ -186,13 +182,6 @@ def test_parse_client_response(self): with pytest.raises(RSConnectException): parse_client_response(None) - def test_is_jwt_compatible_python_version(self): - """ - With setUp() skipping invalid versions, this test should always return True - regardless of the particular python env we're running the tests in - """ - self.assertTrue(is_jwt_compatible_python_version()) - def test_jwt_encoder_constructor(self): encoder = JWTEncoder("issuer", "audience", self.secret_key) diff --git a/tests/test_main.py b/tests/test_main.py index 091a0801..ae43e44c 100644 --- a/tests/test_main.py +++ b/tests/test_main.py @@ -9,7 +9,7 @@ import pytest from click.testing import CliRunner -from rsconnect.json_web_token import SECRET_KEY_ENV, is_jwt_compatible_python_version +from rsconnect.json_web_token import SECRET_KEY_ENV from .utils import ( apply_common_args, @@ -561,9 +561,6 @@ def test_add_shinyapps_missing_options(self): class TestBootstrap(TestCase): def setUp(self): - if not is_jwt_compatible_python_version(): - self.skipTest("JWTs not supported in Python < 3.6") - self.mock_server = "http://localhost:8080" self.mock_uri = "http://localhost:8080/__api__/v1/experimental/bootstrap" self.jwt_keypath = "tests/testdata/jwt/secret.key" diff --git a/tests/test_utils.py b/tests/test_utils.py index 2747954d..d3240973 100644 --- a/tests/test_utils.py +++ b/tests/test_utils.py @@ -1,8 +1,6 @@ from unittest import TestCase from datetime import timedelta -from rsconnect.json_web_token import is_jwt_compatible_python_version - from rsconnect.json_web_token import JWTEncoder from tests.utils import ( @@ -12,10 +10,6 @@ class TestJwtUtils(TestCase): - def setUp(self): - if not is_jwt_compatible_python_version(): - self.skipTest("JWTs not supported in Python < 3.6") - def test_jwt_decoder(self): secret = b"12345678912345678912345678912345" From 3501c3c0a271e5c42b79bd99d03e854cad408e67 Mon Sep 17 00:00:00 2001 From: Michael Marchetti Date: Wed, 4 Jan 2023 12:15:41 -0500 Subject: [PATCH 5/5] add Python 3.11 --- .github/workflows/main.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 7fe9bd24..dcf21d90 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -14,7 +14,7 @@ jobs: matrix: # TODO: work on windows-latest compatibility? os: [ubuntu-latest] - python-version: ['3.7', '3.8', '3.9', '3.10'] + python-version: ['3.7', '3.8', '3.9', '3.10', '3.11'] include: - os: macos-latest python-version: '3.9'