diff --git a/.azure-pipelines/templates/jobs/extended-tests-jobs.yml b/.azure-pipelines/templates/jobs/extended-tests-jobs.yml index 0a72601dd..c2779a076 100644 --- a/.azure-pipelines/templates/jobs/extended-tests-jobs.yml +++ b/.azure-pipelines/templates/jobs/extended-tests-jobs.yml @@ -25,8 +25,9 @@ jobs: linux-integration-nginx-oldest: PYTHON_VERSION: 3.8 TOXENV: integration-nginx-oldest - # python 3.8 integration tests are not run here because they're run as - # part of the standard test suite + linux-py38-integration: + PYTHON_VERSION: 3.8 + TOXENV: integration linux-py39-integration: PYTHON_VERSION: 3.9 TOXENV: integration @@ -36,20 +37,19 @@ jobs: linux-py311-integration: PYTHON_VERSION: 3.11 TOXENV: integration - linux-py312-integration: - PYTHON_VERSION: 3.12 - TOXENV: integration + # python 3.12 integration tests are not run here because they're run as + # part of the standard test suite nginx-compat: TOXENV: nginx_compat linux-integration-rfc2136: IMAGE_NAME: ubuntu-22.04 - PYTHON_VERSION: 3.8 + PYTHON_VERSION: 3.12 TOXENV: integration-dns-rfc2136 le-modification: IMAGE_NAME: ubuntu-22.04 TOXENV: modification farmtest-apache2: - PYTHON_VERSION: 3.8 + PYTHON_VERSION: 3.12 TOXENV: test-farm-apache2 pool: vmImage: $(IMAGE_NAME) diff --git a/.azure-pipelines/templates/jobs/standard-tests-jobs.yml b/.azure-pipelines/templates/jobs/standard-tests-jobs.yml index 65e6bac94..045abcddb 100644 --- a/.azure-pipelines/templates/jobs/standard-tests-jobs.yml +++ b/.azure-pipelines/templates/jobs/standard-tests-jobs.yml @@ -5,14 +5,16 @@ jobs: strategy: matrix: macos-py38-cover: - IMAGE_NAME: macOS-12 + # mac unit+cover tests with the oldest python we support + IMAGE_NAME: macOS-15 PYTHON_VERSION: 3.8 TOXENV: cover # As of pip 23.1.0, builds started failing on macOS unless this flag was set. # See https://github.com/certbot/certbot/pull/9717#issuecomment-1610861794. PIP_USE_PEP517: "true" macos-cover: - IMAGE_NAME: macOS-13 + # mac unit+cover tests with the newest python we support + IMAGE_NAME: macOS-15 TOXENV: cover # See explanation under macos-py38-cover. PIP_USE_PEP517: "true" @@ -21,10 +23,12 @@ jobs: PYTHON_VERSION: 3.8 TOXENV: oldest linux-py38: + # linux unit tests with the oldest python we support IMAGE_NAME: ubuntu-22.04 PYTHON_VERSION: 3.8 TOXENV: py38 linux-cover: + # linux unit+cover tests with the newest python we support IMAGE_NAME: ubuntu-22.04 TOXENV: cover linux-lint: @@ -35,7 +39,6 @@ jobs: TOXENV: mypy linux-integration: IMAGE_NAME: ubuntu-22.04 - PYTHON_VERSION: 3.8 TOXENV: integration apache-compat: IMAGE_NAME: ubuntu-22.04 diff --git a/acme/acme/__init__.py b/acme/acme/__init__.py index 1e21b5896..51034a301 100644 --- a/acme/acme/__init__.py +++ b/acme/acme/__init__.py @@ -6,6 +6,7 @@ This module is an implementation of the `ACME protocol`_. """ import sys +import warnings # This code exists to keep backwards compatibility with people using acme.jose # before it became the standalone josepy package. @@ -19,3 +20,10 @@ for mod in list(sys.modules): # preserved (acme.jose.* is josepy.*) if mod == 'josepy' or mod.startswith('josepy.'): sys.modules['acme.' + mod.replace('josepy', 'jose', 1)] = sys.modules[mod] + +if sys.version_info[:2] == (3, 8): + warnings.warn( + "Python 3.8 support will be dropped in the next planned release of " + "acme. Please upgrade your Python version.", + PendingDeprecationWarning, + ) # pragma: no cover diff --git a/certbot/CHANGELOG.md b/certbot/CHANGELOG.md index dd682d0ba..39251a40e 100644 --- a/certbot/CHANGELOG.md +++ b/certbot/CHANGELOG.md @@ -18,6 +18,8 @@ Certbot adheres to [Semantic Versioning](https://semver.org/). * The `certbot_dns_route53.authenticator` module has been removed. This should not affect any users of the plugin and instead would only affect developers trying to develop on top of the old code. +* Support for Python 3.8 was deprecated and will be removed in our next planned + release. ### Fixed diff --git a/certbot/certbot/__init__.py b/certbot/certbot/__init__.py index cf4ffab00..83099c370 100644 --- a/certbot/certbot/__init__.py +++ b/certbot/certbot/__init__.py @@ -1,4 +1,13 @@ """Certbot client.""" +import sys +import warnings # version number like 1.2.3a0, must have at least 2 parts, like 1.2 __version__ = '2.12.0.dev0' + +if sys.version_info[:2] == (3, 8): + warnings.warn( + "Python 3.8 support will be dropped in the next planned release of " + "certbot. Please upgrade your Python version.", + PendingDeprecationWarning, + ) # pragma: no cover diff --git a/certbot/certbot/_internal/main.py b/certbot/certbot/_internal/main.py index 2fa80e364..107443b5f 100644 --- a/certbot/certbot/_internal/main.py +++ b/certbot/certbot/_internal/main.py @@ -1866,6 +1866,10 @@ def main(cli_args: Optional[List[str]] = None) -> Optional[Union[str, int]]: if config.func != plugins_cmd: # pylint: disable=comparison-with-callable raise + if sys.version_info[:2] == (3, 8): + logger.warning("Python 3.8 support will be dropped in the next planned release " + "of Certbot - please upgrade your Python version.") + with make_displayer(config) as displayer: display_obj.set_display(displayer) diff --git a/certbot/certbot/_internal/snap_config.py b/certbot/certbot/_internal/snap_config.py index e07ee6c08..0b662d459 100644 --- a/certbot/certbot/_internal/snap_config.py +++ b/certbot/certbot/_internal/snap_config.py @@ -33,6 +33,7 @@ _ARCH_TRIPLET_MAP = { 'amd64': 'x86_64-linux-gnu', 's390x': 's390x-linux-gnu', } +CURRENT_PYTHON_VERSION_STRING = 'python3.12' LOGGER = logging.getLogger(__name__) @@ -71,10 +72,35 @@ def prepare_env(cli_args: List[str]) -> List[str]: raise e data = response.json() - connections = ['/snap/{0}/current/lib/python3.12/site-packages/'.format(item['slot']['snap']) - for item in data.get('result', {}).get('established', []) - if item.get('plug', {}).get('plug') == 'plugin' - and item.get('plug-attrs', {}).get('content') == 'certbot-1'] + connections = [] + outdated_plugins = [] + for plugin in data.get('result', {}).get('established', []): + plug: str = plugin.get('plug', {}).get('plug') + plug_content: str = plugin.get('plug-attrs', {}).get('content') + if plug == 'plugin' and plug_content == 'certbot-1': + plugin_name: str = plugin['slot']['snap'] + # First, check that the plugin is using our expected python version, + # i.e. its "read" slot is something like + # "$SNAP/lib/python3.12/site-packages". If not, skip it and print an + # error. + slot_read: str = plugin.get('slot-attrs', {}).get('read', []) + if len(slot_read) != 0 and CURRENT_PYTHON_VERSION_STRING not in slot_read[0]: + outdated_plugins.append(plugin_name) + continue + + connections.append('/snap/{0}/current/lib/{1}/site-packages/'.format( + plugin_name, + CURRENT_PYTHON_VERSION_STRING + )) + + if outdated_plugins: + LOGGER.warning('The following plugins are using an outdated python version and must be ' + 'updated to be compatible with Certbot 3.0. Please see ' + 'https://community.letsencrypt.org/t/' + 'certbot-3-0-could-have-potential-third-party-snap-breakages/226940 ' + 'for more information:') + plugin_list = '\n'.join(' * {}'.format(plugin) for plugin in outdated_plugins) + LOGGER.warning(plugin_list) os.environ['CERTBOT_PLUGIN_PATH'] = ':'.join(connections) diff --git a/certbot/docs/contributing.rst b/certbot/docs/contributing.rst index 7f9dc0db1..2af5f3016 100644 --- a/certbot/docs/contributing.rst +++ b/certbot/docs/contributing.rst @@ -96,17 +96,15 @@ found in the `virtualenv docs`_. Find issues to work on ---------------------- -You can find the open issues in the `github issue tracker`_. Comparatively -easy ones are marked `good first issue`_. If you're starting work on -something, post a comment to let others know and seek feedback on your plan -where appropriate. +You can find the open issues in the `github issue tracker`_. If you're starting +work on something, post a comment to let others know and seek feedback on your +plan where appropriate. Once you've got a working branch, you can open a pull request. All changes in your pull request must have thorough unit test coverage, pass our tests, and be compliant with the :ref:`coding style `. .. _github issue tracker: https://github.com/certbot/certbot/issues -.. _good first issue: https://github.com/certbot/certbot/issues?q=is%3Aopen+is%3Aissue+label%3A%22good+first+issue%22 .. _testing: diff --git a/pytest.ini b/pytest.ini index 65932b071..55c8435fd 100644 --- a/pytest.ini +++ b/pytest.ini @@ -25,6 +25,7 @@ # dependencies) until https://github.com/certbot/certbot/issues/9828 is resolved. # 6) Similarly to 6), CSR support is deprecated in pyOpenSSL since 24.2, we silence # the warning until https://github.com/certbot/certbot/issues/9992 is resolved. +# 7) Ignore our own PendingDeprecationWarning about Python 3.8 soon to be dropped. filterwarnings = error ignore:decodestring\(\) is a deprecated alias:DeprecationWarning:dns @@ -33,3 +34,4 @@ filterwarnings = ignore:.*datetime.utcfromtimestamp\(\) is deprecated:DeprecationWarning:dateutil ignore:X509Extension support in pyOpenSSL is deprecated:DeprecationWarning ignore:CSR support in pyOpenSSL is deprecated:DeprecationWarning + ignore:Python 3.8 support will be dropped:PendingDeprecationWarning diff --git a/tools/snap/generate_dnsplugins_postrefreshhook.sh b/tools/snap/generate_dnsplugins_postrefreshhook.sh index 4a190d06a..cdccc3d95 100755 --- a/tools/snap/generate_dnsplugins_postrefreshhook.sh +++ b/tools/snap/generate_dnsplugins_postrefreshhook.sh @@ -25,7 +25,7 @@ cb_required=\$(grep -oP "version = '\K.*(?=')" \$SNAP/setup.py) \$SNAP/bin/python3 -c "import sys; from packaging import version; sys.exit(1) if\ version.parse('\$cb_installed') < version.parse('\$cb_required') else sys.exit(0)" || exit_code=\$? -if [ "\$exit_code" -eq 1 ]; then +if [ "\$exit_code" = "1" ]; then echo "Certbot is version \$cb_installed but needs to be at least \$cb_required before" \\ "this plugin can be updated; will try again on next refresh." exit 1