Compare commits

...

8 Commits

Author SHA1 Message Date
Brad Warren
bd550c09c2 Release 2.7.3 2023-10-24 13:43:20 -07:00
Brad Warren
01405a8fa6 Update changelog for 2.7.3 release 2023-10-24 13:42:05 -07:00
Brad Warren
5bf833fe28 2.7.3 prep (#9817)
* Update changelog for 2.7.2 release

* Release 2.7.2

* helpful: Add an edge case for arguments w/ contained spaces (#9813)

Fixes #9811

(cherry picked from commit 3ae9d7e03a)

* fixes #9805 (#9816)

(cherry picked from commit d1577280ad)

---------

Co-authored-by: Will Greenberg <willg@eff.org>
2023-10-24 12:49:04 -07:00
Brad Warren
e40741955f Prep for 2.7.2 (#9808)
* helpful: fix handling of abbreviated ConfigArgparse arguments (#9796)

* helpful: fix handling of abbreviated ConfigArgparse arguments

ConfigArgparse allows for "abbreviated" arguments, i.e. just the prefix
of an argument, but it doesn't set the argument sources in these cases.
This commit checks for those cases and sets the sources appropriately.

* failing to find an action raises an error instead of logging

* Update changelog

* Add handling for short arguments, fix equals sign handling

These were silently being dropped before, possibly leading to instances
of `NamespaceConfig.set_by_user()` returning false negatives.

(cherry picked from commit 11e17ef77b)

* Fix finish_release.py (#9800)

* response is value

* rename vars

(cherry picked from commit a96fb4b6ce)

* Merge pull request #9762 from certbot/docs/yaml-config

Add YAML files for Readthedocs requirements

(cherry picked from commit 44046c70c3)

* Update Lexicon requirements to stabilize certbot-dns-ovh behavior (#9802)

* Update minimum Lexicon version required for certbot-dns-ovh

* Add types

* FIx mypy

* Fix lint

* Fix BOTH lint and mypy

(cherry picked from commit 5cf5f36f19)

* simplify code (#9807)

(cherry picked from commit 6f7b5ab1cd)

* Include linting fixes from 8a95c03

---------

Co-authored-by: Will Greenberg <willg@eff.org>
Co-authored-by: Alexis <alexis@eff.org>
Co-authored-by: Adrien Ferrand <adferrand@users.noreply.github.com>
2023-10-19 11:27:21 -07:00
Brad Warren
07b1b0d8b2 Merge pull request #9795 from certbot/candidate-2.7.1-2.7.x
Update 2.7.x from 2.7.1 release
2023-10-11 16:37:48 -07:00
Brad Warren
228e3f2a8d Release 2.7.1 2023-10-10 06:40:52 -07:00
Brad Warren
6624e0b65c Update changelog for 2.7.1 release 2023-10-10 06:39:19 -07:00
Brad Warren
21113d17c7 Prep for 2.7.1 (#9790)
* Bump setup.py's ConfigArgParse version (#9784)

I neglected to do this during #9678, so looks like some pip installs
are failing to get the minimum required version.

(cherry picked from commit 02efc8c5ca)

* Fix dnsimple typo (#9787)

Fixes https://github.com/certbot/certbot/issues/9786.

(cherry picked from commit 4e60a0d03a)

* update pinned dependencies (#9788)

This fixes the security alerts those with access can see at https://github.com/certbot/certbot/security/dependabot.

(cherry picked from commit 5849ff73fb)

* update changelog for configargparse (#9789)

I'd like to do a bug fix release for https://github.com/certbot/certbot/issues/9786. If we're doing one, I figure we may as well flag this change from https://github.com/certbot/certbot/pull/9784 too.

(cherry picked from commit 61773be971)

---------

Co-authored-by: Will Greenberg <willg@eff.org>
2023-10-06 18:59:26 +00:00
57 changed files with 751 additions and 114 deletions

33
acme/.readthedocs.yaml Normal file
View File

@@ -0,0 +1,33 @@
# Read the Docs configuration file for Sphinx projects
# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details
# Required
version: 2
# Set the OS, Python version and other tools you might need
build:
os: ubuntu-22.04
tools:
python: "3.11"
# You can also specify other tool versions:
# Build documentation in the "docs/" directory with Sphinx
sphinx:
configuration: docs/conf.py
# You can configure Sphinx to use a different builder, for instance use the dirhtml builder for simpler URLs
# builder: "dirhtml"
# Fail on all warnings to avoid broken references
fail_on_warning: true
# Optionally build your docs in additional formats such as PDF and ePub
# formats:
- pdf
- epub
# Optional but recommended, declare the Python requirements required
# to build your documentation
# See https://docs.readthedocs.io/en/stable/guides/reproducible-builds.html
python:
install:
- requirements: ../tools/requirements.txt

View File

@@ -3,7 +3,7 @@ import sys
from setuptools import find_packages
from setuptools import setup
version = '2.7.0'
version = '2.7.3'
install_requires = [
'cryptography>=3.2.1',

View File

@@ -1,7 +1,7 @@
from setuptools import find_packages
from setuptools import setup
version = '2.7.0'
version = '2.7.3'
install_requires = [
# We specify the minimum acme and certbot version as the current plugin

View File

@@ -47,15 +47,8 @@ ECDSA_KEY_TYPE = 'ecdsa'
def _suppress_x509_verification_warnings() -> None:
try:
import urllib3
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
except ImportError:
# Handle old versions of request with vendorized urllib3
# pylint: disable=no-member
from requests.packages.urllib3.exceptions import InsecureRequestWarning
requests.packages.urllib3.disable_warnings( # type: ignore[attr-defined]
InsecureRequestWarning)
import urllib3
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
def check_until_timeout(url: str, attempts: int = 30) -> None:

View File

@@ -19,9 +19,11 @@ install_requires = [
'pywin32>=300 ; sys_platform == "win32"',
'pyyaml',
'pytz>=2019.3',
'requests',
# requests unvendored its dependencies in version 2.16.0 and this code relies on that for
# calling `urllib3.disable_warnings`.
'requests>=2.16.0',
'setuptools',
'types-python-dateutil'
'types-python-dateutil',
]
setup(

View File

@@ -1,7 +1,7 @@
from setuptools import find_packages
from setuptools import setup
version = '2.7.0'
version = '2.7.3'
install_requires = [
'certbot',

View File

@@ -0,0 +1,33 @@
# Read the Docs configuration file for Sphinx projects
# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details
# Required
version: 2
# Set the OS, Python version and other tools you might need
build:
os: ubuntu-22.04
tools:
python: "3.11"
# You can also specify other tool versions:
# Build documentation in the "docs/" directory with Sphinx
sphinx:
configuration: docs/conf.py
# You can configure Sphinx to use a different builder, for instance use the dirhtml builder for simpler URLs
# builder: "dirhtml"
# Fail on all warnings to avoid broken references
fail_on_warning: true
# Optionally build your docs in additional formats such as PDF and ePub
# formats:
- pdf
- epub
# Optional but recommended, declare the Python requirements required
# to build your documentation
# See https://docs.readthedocs.io/en/stable/guides/reproducible-builds.html
python:
install:
- requirements: ../tools/requirements.txt

View File

@@ -4,7 +4,7 @@ import sys
from setuptools import find_packages
from setuptools import setup
version = '2.7.0'
version = '2.7.3'
install_requires = [
'cloudflare>=1.5.1',

View File

@@ -0,0 +1,33 @@
# Read the Docs configuration file for Sphinx projects
# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details
# Required
version: 2
# Set the OS, Python version and other tools you might need
build:
os: ubuntu-22.04
tools:
python: "3.11"
# You can also specify other tool versions:
# Build documentation in the "docs/" directory with Sphinx
sphinx:
configuration: docs/conf.py
# You can configure Sphinx to use a different builder, for instance use the dirhtml builder for simpler URLs
# builder: "dirhtml"
# Fail on all warnings to avoid broken references
fail_on_warning: true
# Optionally build your docs in additional formats such as PDF and ePub
# formats:
- pdf
- epub
# Optional but recommended, declare the Python requirements required
# to build your documentation
# See https://docs.readthedocs.io/en/stable/guides/reproducible-builds.html
python:
install:
- requirements: ../tools/requirements.txt

View File

@@ -4,7 +4,7 @@ import sys
from setuptools import find_packages
from setuptools import setup
version = '2.7.0'
version = '2.7.3'
install_requires = [
'python-digitalocean>=1.11', # 1.15.0 or newer is recommended for TTL support

View File

@@ -0,0 +1,33 @@
# Read the Docs configuration file for Sphinx projects
# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details
# Required
version: 2
# Set the OS, Python version and other tools you might need
build:
os: ubuntu-22.04
tools:
python: "3.11"
# You can also specify other tool versions:
# Build documentation in the "docs/" directory with Sphinx
sphinx:
configuration: docs/conf.py
# You can configure Sphinx to use a different builder, for instance use the dirhtml builder for simpler URLs
# builder: "dirhtml"
# Fail on all warnings to avoid broken references
fail_on_warning: true
# Optionally build your docs in additional formats such as PDF and ePub
# formats:
- pdf
- epub
# Optional but recommended, declare the Python requirements required
# to build your documentation
# See https://docs.readthedocs.io/en/stable/guides/reproducible-builds.html
python:
install:
- requirements: ../tools/requirements.txt

View File

@@ -39,7 +39,7 @@ class Authenticator(dns_common_lexicon.LexiconDNSAuthenticator):
@property
def _provider_name(self) -> str:
return 'dnssimple'
return 'dnsimple'
def _handle_http_error(self, e: HTTPError, domain_name: str) -> errors.PluginError:
hint = None

View File

@@ -3,6 +3,7 @@ from unittest import mock
import sys
import pytest
from requests import Response
from requests.exceptions import HTTPError
from certbot.compat import os
@@ -16,7 +17,7 @@ TOKEN = 'foo'
class AuthenticatorTest(test_util.TempDirTestCase,
dns_test_common_lexicon.BaseLexiconDNSAuthenticatorTest):
LOGIN_ERROR = HTTPError('401 Client Error: Unauthorized for url: ...')
LOGIN_ERROR = HTTPError('401 Client Error: Unauthorized for url: ...', response=Response())
def setUp(self):
super().setUp()

View File

@@ -4,7 +4,7 @@ import sys
from setuptools import find_packages
from setuptools import setup
version = '2.7.0'
version = '2.7.3'
install_requires = [
# This version of lexicon is required to address the problem described in

View File

@@ -0,0 +1,33 @@
# Read the Docs configuration file for Sphinx projects
# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details
# Required
version: 2
# Set the OS, Python version and other tools you might need
build:
os: ubuntu-22.04
tools:
python: "3.11"
# You can also specify other tool versions:
# Build documentation in the "docs/" directory with Sphinx
sphinx:
configuration: docs/conf.py
# You can configure Sphinx to use a different builder, for instance use the dirhtml builder for simpler URLs
# builder: "dirhtml"
# Fail on all warnings to avoid broken references
fail_on_warning: true
# Optionally build your docs in additional formats such as PDF and ePub
# formats:
- pdf
- epub
# Optional but recommended, declare the Python requirements required
# to build your documentation
# See https://docs.readthedocs.io/en/stable/guides/reproducible-builds.html
python:
install:
- requirements: ../tools/requirements.txt

View File

@@ -4,6 +4,7 @@ import sys
from unittest import mock
import pytest
from requests import Response
from requests.exceptions import HTTPError
from certbot.compat import os
@@ -19,8 +20,8 @@ SECRET_KEY = 'bar'
class AuthenticatorTest(test_util.TempDirTestCase,
dns_test_common_lexicon.BaseLexiconDNSAuthenticatorTest):
DOMAIN_NOT_FOUND = HTTPError(f'404 Client Error: Not Found for url: {DOMAIN}.')
LOGIN_ERROR = HTTPError(f'403 Client Error: Forbidden for url: {DOMAIN}.')
DOMAIN_NOT_FOUND = HTTPError(f'404 Client Error: Not Found for url: {DOMAIN}.', response=Response())
LOGIN_ERROR = HTTPError(f'403 Client Error: Forbidden for url: {DOMAIN}.', response=Response())
def setUp(self):
super().setUp()

View File

@@ -4,7 +4,7 @@ import sys
from setuptools import find_packages
from setuptools import setup
version = '2.7.0'
version = '2.7.3'
install_requires = [
'dns-lexicon>=3.14.1',

View File

@@ -0,0 +1,33 @@
# Read the Docs configuration file for Sphinx projects
# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details
# Required
version: 2
# Set the OS, Python version and other tools you might need
build:
os: ubuntu-22.04
tools:
python: "3.11"
# You can also specify other tool versions:
# Build documentation in the "docs/" directory with Sphinx
sphinx:
configuration: docs/conf.py
# You can configure Sphinx to use a different builder, for instance use the dirhtml builder for simpler URLs
# builder: "dirhtml"
# Fail on all warnings to avoid broken references
fail_on_warning: true
# Optionally build your docs in additional formats such as PDF and ePub
# formats:
- pdf
- epub
# Optional but recommended, declare the Python requirements required
# to build your documentation
# See https://docs.readthedocs.io/en/stable/guides/reproducible-builds.html
python:
install:
- requirements: ../tools/requirements.txt

View File

@@ -5,6 +5,7 @@ import unittest
from unittest import mock
import pytest
from requests import Response
from requests.exceptions import HTTPError
from certbot.compat import os
@@ -20,8 +21,8 @@ API_SECRET = 'MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAw'
class AuthenticatorTest(test_util.TempDirTestCase,
dns_test_common_lexicon.BaseLexiconDNSAuthenticatorTest):
DOMAIN_NOT_FOUND = HTTPError(f'404 Client Error: Not Found for url: {DOMAIN}.')
LOGIN_ERROR = HTTPError(f'401 Client Error: Unauthorized for url: {DOMAIN}.')
DOMAIN_NOT_FOUND = HTTPError(f'404 Client Error: Not Found for url: {DOMAIN}.', response=Response())
LOGIN_ERROR = HTTPError(f'401 Client Error: Unauthorized for url: {DOMAIN}.', response=Response())
def setUp(self):
super().setUp()

View File

@@ -4,7 +4,7 @@ import sys
from setuptools import find_packages
from setuptools import setup
version = '2.7.0'
version = '2.7.3'
install_requires = [
'dns-lexicon>=3.14.1',

View File

@@ -0,0 +1,33 @@
# Read the Docs configuration file for Sphinx projects
# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details
# Required
version: 2
# Set the OS, Python version and other tools you might need
build:
os: ubuntu-22.04
tools:
python: "3.11"
# You can also specify other tool versions:
# Build documentation in the "docs/" directory with Sphinx
sphinx:
configuration: docs/conf.py
# You can configure Sphinx to use a different builder, for instance use the dirhtml builder for simpler URLs
# builder: "dirhtml"
# Fail on all warnings to avoid broken references
fail_on_warning: true
# Optionally build your docs in additional formats such as PDF and ePub
# formats:
- pdf
- epub
# Optional but recommended, declare the Python requirements required
# to build your documentation
# See https://docs.readthedocs.io/en/stable/guides/reproducible-builds.html
python:
install:
- requirements: ../tools/requirements.txt

View File

@@ -4,7 +4,7 @@ import sys
from setuptools import find_packages
from setuptools import setup
version = '2.7.0'
version = '2.7.3'
install_requires = [
'google-api-python-client>=1.6.5',

View File

@@ -0,0 +1,33 @@
# Read the Docs configuration file for Sphinx projects
# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details
# Required
version: 2
# Set the OS, Python version and other tools you might need
build:
os: ubuntu-22.04
tools:
python: "3.11"
# You can also specify other tool versions:
# Build documentation in the "docs/" directory with Sphinx
sphinx:
configuration: docs/conf.py
# You can configure Sphinx to use a different builder, for instance use the dirhtml builder for simpler URLs
# builder: "dirhtml"
# Fail on all warnings to avoid broken references
fail_on_warning: true
# Optionally build your docs in additional formats such as PDF and ePub
# formats:
- pdf
- epub
# Optional but recommended, declare the Python requirements required
# to build your documentation
# See https://docs.readthedocs.io/en/stable/guides/reproducible-builds.html
python:
install:
- requirements: ../tools/requirements.txt

View File

@@ -4,7 +4,7 @@ import sys
from setuptools import find_packages
from setuptools import setup
version = '2.7.0'
version = '2.7.3'
install_requires = [
'dns-lexicon>=3.14.1',

View File

@@ -0,0 +1,33 @@
# Read the Docs configuration file for Sphinx projects
# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details
# Required
version: 2
# Set the OS, Python version and other tools you might need
build:
os: ubuntu-22.04
tools:
python: "3.11"
# You can also specify other tool versions:
# Build documentation in the "docs/" directory with Sphinx
sphinx:
configuration: docs/conf.py
# You can configure Sphinx to use a different builder, for instance use the dirhtml builder for simpler URLs
# builder: "dirhtml"
# Fail on all warnings to avoid broken references
fail_on_warning: true
# Optionally build your docs in additional formats such as PDF and ePub
# formats:
- pdf
- epub
# Optional but recommended, declare the Python requirements required
# to build your documentation
# See https://docs.readthedocs.io/en/stable/guides/reproducible-builds.html
python:
install:
- requirements: ../tools/requirements.txt

View File

@@ -3,6 +3,7 @@ import sys
from unittest import mock
import pytest
from requests import Response
from requests.exceptions import HTTPError
from certbot.compat import os
@@ -17,7 +18,7 @@ TOKEN = 'foo'
class AuthenticatorTest(test_util.TempDirTestCase,
dns_test_common_lexicon.BaseLexiconDNSAuthenticatorTest):
LOGIN_ERROR = HTTPError("401 Client Error: Unauthorized for url: ...")
LOGIN_ERROR = HTTPError("401 Client Error: Unauthorized for url: ...", response=Response())
def setUp(self):
super().setUp()

View File

@@ -4,7 +4,7 @@ import sys
from setuptools import find_packages
from setuptools import setup
version = '2.7.0'
version = '2.7.3'
install_requires = [
'dns-lexicon>=3.14.1',

View File

@@ -0,0 +1,33 @@
# Read the Docs configuration file for Sphinx projects
# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details
# Required
version: 2
# Set the OS, Python version and other tools you might need
build:
os: ubuntu-22.04
tools:
python: "3.11"
# You can also specify other tool versions:
# Build documentation in the "docs/" directory with Sphinx
sphinx:
configuration: docs/conf.py
# You can configure Sphinx to use a different builder, for instance use the dirhtml builder for simpler URLs
# builder: "dirhtml"
# Fail on all warnings to avoid broken references
fail_on_warning: true
# Optionally build your docs in additional formats such as PDF and ePub
# formats:
- pdf
- epub
# Optional but recommended, declare the Python requirements required
# to build your documentation
# See https://docs.readthedocs.io/en/stable/guides/reproducible-builds.html
python:
install:
- requirements: ../tools/requirements.txt

View File

@@ -3,6 +3,7 @@ import sys
from unittest import mock
import pytest
from requests import Response
from requests.exceptions import HTTPError
from certbot.compat import os
@@ -17,8 +18,8 @@ API_KEY = 'foo'
class AuthenticatorTest(test_util.TempDirTestCase,
dns_test_common_lexicon.BaseLexiconDNSAuthenticatorTest):
DOMAIN_NOT_FOUND = HTTPError(f'404 Client Error: Not Found for url: {DOMAIN}.')
LOGIN_ERROR = HTTPError(f'401 Client Error: Unauthorized for url: {DOMAIN}.')
DOMAIN_NOT_FOUND = HTTPError(f'404 Client Error: Not Found for url: {DOMAIN}.', response=Response())
LOGIN_ERROR = HTTPError(f'401 Client Error: Unauthorized for url: {DOMAIN}.', response=Response())
def setUp(self):
super().setUp()

View File

@@ -4,7 +4,7 @@ import sys
from setuptools import find_packages
from setuptools import setup
version = '2.7.0'
version = '2.7.3'
install_requires = [
'dns-lexicon>=3.14.1',

View File

@@ -0,0 +1,33 @@
# Read the Docs configuration file for Sphinx projects
# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details
# Required
version: 2
# Set the OS, Python version and other tools you might need
build:
os: ubuntu-22.04
tools:
python: "3.11"
# You can also specify other tool versions:
# Build documentation in the "docs/" directory with Sphinx
sphinx:
configuration: docs/conf.py
# You can configure Sphinx to use a different builder, for instance use the dirhtml builder for simpler URLs
# builder: "dirhtml"
# Fail on all warnings to avoid broken references
fail_on_warning: true
# Optionally build your docs in additional formats such as PDF and ePub
# formats:
- pdf
- epub
# Optional but recommended, declare the Python requirements required
# to build your documentation
# See https://docs.readthedocs.io/en/stable/guides/reproducible-builds.html
python:
install:
- requirements: ../tools/requirements.txt

View File

@@ -3,6 +3,7 @@ from unittest import mock
import sys
import pytest
from requests import Response
from requests.exceptions import HTTPError
from certbot.compat import os
@@ -20,8 +21,7 @@ class AuthenticatorTest(test_util.TempDirTestCase,
dns_test_common_lexicon.BaseLexiconDNSAuthenticatorTest):
DOMAIN_NOT_FOUND = Exception('Domain example.com not found')
LOGIN_ERROR = HTTPError('403 Client Error: Forbidden for url: https://eu.api.ovh.com/1.0/...')
LOGIN_ERROR = HTTPError('403 Client Error: Forbidden for url: https://eu.api.ovh.com/1.0/...', response=Response())
def setUp(self):
super().setUp()

View File

@@ -4,10 +4,10 @@ import sys
from setuptools import find_packages
from setuptools import setup
version = '2.7.0'
version = '2.7.3'
install_requires = [
'dns-lexicon>=3.14.1',
'dns-lexicon>=3.15.1',
'setuptools>=41.6.0',
]

View File

@@ -0,0 +1,33 @@
# Read the Docs configuration file for Sphinx projects
# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details
# Required
version: 2
# Set the OS, Python version and other tools you might need
build:
os: ubuntu-22.04
tools:
python: "3.11"
# You can also specify other tool versions:
# Build documentation in the "docs/" directory with Sphinx
sphinx:
configuration: docs/conf.py
# You can configure Sphinx to use a different builder, for instance use the dirhtml builder for simpler URLs
# builder: "dirhtml"
# Fail on all warnings to avoid broken references
fail_on_warning: true
# Optionally build your docs in additional formats such as PDF and ePub
# formats:
- pdf
- epub
# Optional but recommended, declare the Python requirements required
# to build your documentation
# See https://docs.readthedocs.io/en/stable/guides/reproducible-builds.html
python:
install:
- requirements: ../tools/requirements.txt

View File

@@ -4,7 +4,7 @@ import sys
from setuptools import find_packages
from setuptools import setup
version = '2.7.0'
version = '2.7.3'
install_requires = [
'dnspython>=1.15.0',

View File

@@ -0,0 +1,33 @@
# Read the Docs configuration file for Sphinx projects
# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details
# Required
version: 2
# Set the OS, Python version and other tools you might need
build:
os: ubuntu-22.04
tools:
python: "3.11"
# You can also specify other tool versions:
# Build documentation in the "docs/" directory with Sphinx
sphinx:
configuration: docs/conf.py
# You can configure Sphinx to use a different builder, for instance use the dirhtml builder for simpler URLs
# builder: "dirhtml"
# Fail on all warnings to avoid broken references
fail_on_warning: true
# Optionally build your docs in additional formats such as PDF and ePub
# formats:
- pdf
- epub
# Optional but recommended, declare the Python requirements required
# to build your documentation
# See https://docs.readthedocs.io/en/stable/guides/reproducible-builds.html
python:
install:
- requirements: ../tools/requirements.txt

View File

@@ -4,7 +4,7 @@ import sys
from setuptools import find_packages
from setuptools import setup
version = '2.7.0'
version = '2.7.3'
install_requires = [
'boto3>=1.15.15',

View File

@@ -0,0 +1,33 @@
# Read the Docs configuration file for Sphinx projects
# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details
# Required
version: 2
# Set the OS, Python version and other tools you might need
build:
os: ubuntu-22.04
tools:
python: "3.11"
# You can also specify other tool versions:
# Build documentation in the "docs/" directory with Sphinx
sphinx:
configuration: docs/conf.py
# You can configure Sphinx to use a different builder, for instance use the dirhtml builder for simpler URLs
# builder: "dirhtml"
# Fail on all warnings to avoid broken references
fail_on_warning: true
# Optionally build your docs in additional formats such as PDF and ePub
# formats:
- pdf
- epub
# Optional but recommended, declare the Python requirements required
# to build your documentation
# See https://docs.readthedocs.io/en/stable/guides/reproducible-builds.html
python:
install:
- requirements: ../tools/requirements.txt

View File

@@ -3,6 +3,7 @@ import sys
from unittest import mock
import pytest
from requests import Response
from requests.exceptions import HTTPError
from certbot.compat import os
@@ -18,8 +19,8 @@ API_SECRET = 'MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAw'
class AuthenticatorTest(test_util.TempDirTestCase,
dns_test_common_lexicon.BaseLexiconDNSAuthenticatorTest):
DOMAIN_NOT_FOUND = HTTPError(f'404 Client Error: Not Found for url: {DOMAIN}.')
LOGIN_ERROR = HTTPError(f'401 Client Error: Unauthorized for url: {DOMAIN}.')
DOMAIN_NOT_FOUND = HTTPError(f'404 Client Error: Not Found for url: {DOMAIN}.', response=Response())
LOGIN_ERROR = HTTPError(f'401 Client Error: Unauthorized for url: {DOMAIN}.', response=Response())
def setUp(self):
super().setUp()

View File

@@ -4,7 +4,7 @@ import sys
from setuptools import find_packages
from setuptools import setup
version = '2.7.0'
version = '2.7.3'
install_requires = [
'dns-lexicon>=3.14.1',

View File

@@ -1,7 +1,7 @@
from setuptools import find_packages
from setuptools import setup
version = '2.7.0'
version = '2.7.3'
install_requires = [
# We specify the minimum acme and certbot version as the current plugin

33
certbot/.readthedocs.yaml Normal file
View File

@@ -0,0 +1,33 @@
# Read the Docs configuration file for Sphinx projects
# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details
# Required
version: 2
# Set the OS, Python version and other tools you might need
build:
os: ubuntu-22.04
tools:
python: "3.11"
# You can also specify other tool versions:
# Build documentation in the "docs/" directory with Sphinx
sphinx:
configuration: docs/conf.py
# You can configure Sphinx to use a different builder, for instance use the dirhtml builder for simpler URLs
# builder: "dirhtml"
# Fail on all warnings to avoid broken references
fail_on_warning: true
# Optionally build your docs in additional formats such as PDF and ePub
# formats:
- pdf
- epub
# Optional but recommended, declare the Python requirements required
# to build your documentation
# See https://docs.readthedocs.io/en/stable/guides/reproducible-builds.html
python:
install:
- requirements: ../tools/requirements.txt

View File

@@ -2,6 +2,38 @@
Certbot adheres to [Semantic Versioning](https://semver.org/).
## 2.7.3 - 2023-10-24
### Fixed
* Fixed a bug where arguments with contained spaces weren't being handled correctly
* Fixed a bug that caused the ACME account to not be properly restored on
renewal causing problems in setups where the user had multiple accounts with
the same ACME server.
More details about these changes can be found on our GitHub repo.
## 2.7.2 - 2023-10-19
### Fixed
* `certbot-dns-ovh` plugin now requires `lexicon>=3.15.1` to ensure a consistent behavior with OVH APIs.
* Fixed a bug where argument sources weren't correctly detected in abbreviated
arguments, short arguments, and some other circumstances
More details about these changes can be found on our GitHub repo.
## 2.7.1 - 2023-10-10
### Fixed
* Fixed a bug that broke the DNS plugin for DNSimple that was introduced in
version 2.7.0 of the plugin.
* Correctly specified the new minimum version of the ConfigArgParse package
that Certbot requires which is 1.5.3.
More details about these changes can be found on our GitHub repo.
## 2.7.0 - 2023-10-03
### Added

View File

@@ -3,7 +3,7 @@ import sys
import warnings
# version number like 1.2.3a0, must have at least 2 parts, like 1.2
__version__ = '2.7.0'
__version__ = '2.7.3'
if sys.version_info[:2] == (3, 7):
warnings.warn(

View File

@@ -187,10 +187,12 @@ class HelpfulArgumentParser:
# 2. config files
# 3. env vars (shouldn't be any)
# 4. command line
def update_result(settings_dict: Dict[str, Tuple[configargparse.Action, str]],
source: ArgumentSource) -> None:
actions = [action for _, (action, _) in settings_dict.items()]
result.update({ action.dest: source for action in actions})
actions = [self._find_action_for_arg(arg) if action is None else action
for arg, (action, _) in settings_dict.items()]
result.update({ action.dest: source for action in actions })
# config file sources look like "config_file|<name of file>"
for source_key in source_to_settings_dict:
@@ -203,17 +205,61 @@ class HelpfulArgumentParser:
if 'command_line' in source_to_settings_dict:
settings_dict: Dict[str, Tuple[None, List[str]]]
settings_dict = source_to_settings_dict['command_line'] # type: ignore
(_, args) = settings_dict['']
args = [arg for arg in args if arg.startswith('-')]
(_, unprocessed_args) = settings_dict['']
args = []
for arg in unprocessed_args:
# ignore non-arguments
if not arg.startswith('-'):
continue
# special case for config file argument, which we don't have an action for
if arg in ['-c', '--config']:
result['config_dir'] = ArgumentSource.COMMAND_LINE
continue
if '=' in arg:
arg = arg.split('=')[0]
elif ' ' in arg:
arg = arg.split(' ')[0]
if arg.startswith('--'):
args.append(arg)
# for short args (ones that start with a single hyphen), handle
# the case of multiple short args together, e.g. "-tvm"
else:
for short_arg in arg[1:]:
args.append(f"-{short_arg}")
for arg in args:
# find the action corresponding to this arg
for action in self.actions:
if arg in action.option_strings:
result[action.dest] = ArgumentSource.COMMAND_LINE
continue
action = self._find_action_for_arg(arg)
result[action.dest] = ArgumentSource.COMMAND_LINE
return result
def _find_action_for_arg(self, arg: str) -> configargparse.Action:
# Finds a configargparse Action which matches the given arg, where arg
# can either be preceded by hyphens (as on the command line) or not (as
# in config files)
# if the argument doesn't have leading hypens, prefix it so it can be
# compared directly w/ action option strings
if arg[0] != '-':
arg = '--' + arg
# first, check for exact matches
for action in self.actions:
if arg in action.option_strings:
return action
# now check for abbreviated (i.e. prefix) matches
for action in self.actions:
for option_string in action.option_strings:
if option_string.startswith(arg):
return action
raise AssertionError(f"Action corresponding to argument {arg} is None")
def parse_args(self) -> NamespaceConfig:
"""Parses command line arguments and returns the result.

View File

@@ -182,9 +182,9 @@ class PluginsRegistry(Mapping):
plugin_paths = plugin_paths_string.split(':') if plugin_paths_string else []
# XXX should ensure this only happens once
sys.path.extend(plugin_paths)
entry_points = list(importlib_metadata.entry_points(
entry_points = list(importlib_metadata.entry_points( # pylint: disable=unexpected-keyword-arg
group=constants.SETUPTOOLS_PLUGINS_ENTRY_POINT))
old_entry_points = list(importlib_metadata.entry_points(
old_entry_points = list(importlib_metadata.entry_points( # pylint: disable=unexpected-keyword-arg
group=constants.OLD_SETUPTOOLS_PLUGINS_ENTRY_POINT))
for entry_point in entry_points + old_entry_points:
try:

View File

@@ -194,6 +194,7 @@ def restore_required_config_elements(config: configuration.NamespaceConfig,
"""
updated_values = {}
required_items = itertools.chain(
(("pref_challs", _restore_pref_challs),),
zip(BOOL_CONFIG_ITEMS, itertools.repeat(_restore_bool)),
@@ -202,7 +203,9 @@ def restore_required_config_elements(config: configuration.NamespaceConfig,
for item_name, restore_func in required_items:
if item_name in renewalparams and not config.set_by_user(item_name):
value = restore_func(item_name, renewalparams[item_name])
setattr(config, item_name, value)
updated_values[item_name] = value
for key, value in updated_values.items():
setattr(config, key, value)
def _remove_deprecated_config_elements(renewalparams: Mapping[str, Any]) -> Dict[str, Any]:

View File

@@ -552,6 +552,55 @@ class ParseTest(unittest.TestCase):
])
assert_value_and_source(namespace, 'server', COMMAND_LINE_VALUE, ArgumentSource.COMMAND_LINE)
def test_abbreviated_arguments(self):
# Argparse's "allow_abbrev" option (which is True by default) allows
# for unambiguous partial arguments (e.g. "--preferred-chal dns" will be
# interepreted the same as "--preferred-challenges dns")
namespace = self.parse('--preferred-chal dns --no-dir')
assert_set_by_user_with_value(namespace, 'pref_challs', ['dns-01'])
assert_set_by_user_with_value(namespace, 'directory_hooks', False)
with tempfile.NamedTemporaryFile() as tmp_config:
tmp_config.close() # close now because of compatibility issues on Windows
with open(tmp_config.name, 'w') as file_h:
file_h.write('preferred-chal = dns')
namespace = self.parse([
'certonly',
'--config', tmp_config.name,
])
assert_set_by_user_with_value(namespace, 'pref_challs', ['dns-01'])
@mock.patch('certbot._internal.hooks.validate_hooks')
def test_argument_with_equals(self, unsused_mock_validate_hooks):
namespace = self.parse('-d=example.com')
assert_set_by_user_with_value(namespace, 'domains', ['example.com'])
# make sure it doesn't choke on equals signs being present in the argument value
plugins = disco.PluginsRegistry.find_all()
namespace = cli.prepare_and_parse_args(plugins, ['run', '--pre-hook="foo=bar"'])
assert_set_by_user_with_value(namespace, 'pre_hook', '"foo=bar"')
def test_adjacent_short_args(self):
namespace = self.parse('-tv')
assert_set_by_user_with_value(namespace, 'text_mode', True)
assert_set_by_user_with_value(namespace, 'verbose_count', 1)
namespace = self.parse('-tvvv')
assert_set_by_user_with_value(namespace, 'text_mode', True)
assert_set_by_user_with_value(namespace, 'verbose_count', 3)
namespace = self.parse('-tvm foo@example.com')
assert_set_by_user_with_value(namespace, 'text_mode', True)
assert_set_by_user_with_value(namespace, 'verbose_count', 1)
assert_set_by_user_with_value(namespace, 'email', 'foo@example.com')
def test_arg_with_contained_spaces(self):
# This can happen if a user specifies an arg like "-d foo.com" enclosed
# in double quotes, or as its own line in a docker-compose.yml file (as
# in #9811)
namespace = self.parse(['certonly', '-d foo.com'])
assert_set_by_user_with_value(namespace, 'domains', ['foo.com'])
if __name__ == '__main__':
sys.exit(pytest.main(sys.argv[1:] + [__file__])) # pragma: no cover

View File

@@ -253,6 +253,18 @@ class RestoreRequiredConfigElementsTest(test_util.ConfigTestCase):
self._call(self.config, {'server': constants.V1_URI})
assert self.config.server == constants.CLI_DEFAULTS['server']
def test_related_values(self):
# certbot.configuration.NamespaceConfig.set_by_user considers some values as related to each
# other and considers both set by the user if either is. This test ensures all renewal
# parameters are restored regardless of their restoration order or relation between values.
# See https://github.com/certbot/certbot/issues/9805 for more info.
renewalparams = {
'server': 'https://example.org',
'account': 'somehash',
}
self._call(self.config, renewalparams)
self.assertEqual(self.config.account, renewalparams['account'])
class DescribeResultsTest(unittest.TestCase):
"""Tests for certbot._internal.renewal._renew_describe_results."""

View File

@@ -30,9 +30,9 @@ try:
from lexicon.config import ConfigResolver
from lexicon.interfaces import Provider
except ImportError: # pragma: no cover
Client = None
ConfigResolver = None
Provider = None
Client = None # type: ignore
ConfigResolver = None # type: ignore
Provider = None # type: ignore
logger = logging.getLogger(__name__)
@@ -148,19 +148,18 @@ def build_lexicon_config(lexicon_provider_name: str,
.. deprecated:: 2.7.0
Please use certbot.plugins.dns_common_lexicon.LexiconDNSAuthenticator instead.
"""
config: Union[ConfigResolver, Dict[str, Any]] = {'provider_name': lexicon_provider_name}
config.update(lexicon_options)
if not ConfigResolver:
config_dict: Dict[str, Any] = {'provider_name': lexicon_provider_name}
config_dict.update(lexicon_options)
if ConfigResolver is None:
# Lexicon 2.x
config.update(provider_options)
config_dict.update(provider_options)
return config_dict
else:
# Lexicon 3.x
provider_config: Dict[str, Any] = {}
provider_config.update(provider_options)
config[lexicon_provider_name] = provider_config
config = ConfigResolver().with_dict(config).with_env()
return config
config_dict[lexicon_provider_name] = provider_config
return ConfigResolver().with_dict(config_dict).with_env()
class LexiconDNSAuthenticator(dns_common.DNSAuthenticator):

View File

@@ -13,6 +13,7 @@ from unittest.mock import MagicMock
import warnings
import josepy as jose
from requests import Response
from requests.exceptions import HTTPError
from requests.exceptions import RequestException
@@ -37,8 +38,8 @@ KEY = jose.JWKRSA.load(test_util.load_vector("rsa512_key.pem"))
DOMAIN_NOT_FOUND = Exception('No domain found')
GENERIC_ERROR = RequestException
LOGIN_ERROR = HTTPError('400 Client Error: ...')
UNKNOWN_LOGIN_ERROR = HTTPError('500 Surprise! Error: ...')
LOGIN_ERROR = HTTPError('400 Client Error: ...', response=Response())
UNKNOWN_LOGIN_ERROR = HTTPError('500 Surprise! Error: ...', response=Response())
class _AuthenticatorCallableLexiconTestCase(_AuthenticatorCallableTestCase, Protocol):

View File

@@ -36,7 +36,7 @@ manage your account:
--agree-tos Agree to the ACME server's Subscriber Agreement
-m EMAIL Email address for important account notifications
options:
optional arguments:
-h, --help show this help message and exit
-c CONFIG_FILE, --config CONFIG_FILE
path to config file (default: /etc/letsencrypt/cli.ini
@@ -122,7 +122,7 @@ options:
case, and to know when to deprecate support for past
Python versions and flags. If you wish to hide this
information from the Let's Encrypt server, set this to
"". (default: CertbotACMEClient/2.7.0 (certbot;
"". (default: CertbotACMEClient/2.7.3 (certbot;
OS_NAME OS_VERSION) Authenticator/XXX Installer/YYY
(SUBCOMMAND; flags: FLAGS) Py/major.minor.patchlevel).
The flags encoded in the user agent are: --duplicate,

View File

@@ -28,10 +28,7 @@ install_requires = [
# simplicity. See https://github.com/certbot/certbot/issues/8761 for more
# info.
f'acme>={version}',
# We technically need ConfigArgParse 0.10.0 for Python 2.6 support, but
# saying so here causes a runtime error against our temporary fork of 0.9.3
# in which we added 2.6 support (see #2243), so we relax the requirement.
'ConfigArgParse>=0.9.3',
'ConfigArgParse>=1.5.3',
'configobj>=5.0.6',
'cryptography>=3.2.1',
'distro>=1.0.1',

View File

@@ -73,7 +73,7 @@ def parse_args(args):
parser.add_argument('--css', type=str, required=True, help='hostname of code signing server')
return parser.parse_args(args)
def publish_windows(css):
"""SSH into CSS and trigger downloading Azure Pipeline assets, sign, and upload to Github
@@ -83,7 +83,7 @@ def publish_windows(css):
username = input("CSS username (usually EFF username): ")
host = css
command = "ssh -t {}@{} bash /opt/certbot-misc/css/venv.sh".format(username,host)
print("SSH into CSS to trigger signing and uploading of Windows installer...")
subprocess.run(command, check=True, universal_newlines=True, shell=True)
@@ -182,16 +182,16 @@ def fetch_version_number(major_version=None):
:type major_version: str or None
:returns: version number
"""
# Create a connection to the azure org
organization_url = 'https://dev.azure.com/certbot'
connection = Connection(base_url=organization_url)
# Find the build artifacts
build_client = connection.clients.get_build_client()
get_builds_response = build_client.get_builds('certbot', definitions='3')
for build in get_builds_response.value:
builds = build_client.get_builds('certbot', definitions='3')
for build in builds:
version = build_client.get_build('certbot', build.id).source_branch.split('v')[1]
if major_version is None or version.split('.')[0] == major_version:
return version
@@ -206,7 +206,7 @@ def main(args):
# Once the GitHub release has been published, trying to publish it
# again fails. Publishing the snaps can be done multiple times though
# so we do that first to make it easier to run the script again later
# if something goes wrong.
# if something goes wrong.
promote_snaps(ALL_SNAPS, 'beta', version)
publish_windows(css)

View File

@@ -3,7 +3,7 @@
apacheconfig==0.3.2 ; python_version >= "3.7" and python_version < "3.8"
appdirs==1.4.4 ; python_version >= "3.7" and python_version < "3.8"
asn1crypto==0.24.0 ; python_version >= "3.7" and python_version < "3.8"
astroid==2.15.6 ; python_full_version >= "3.7.2" and python_version < "3.8"
astroid==2.15.8 ; python_full_version >= "3.7.2" and python_version < "3.8"
beautifulsoup4==4.12.2 ; python_version >= "3.7" and python_version < "3.8"
boto3==1.15.15 ; python_version >= "3.7" and python_version < "3.8"
botocore==1.18.15 ; python_version >= "3.7" and python_version < "3.8"
@@ -21,7 +21,7 @@ cython==0.29.36 ; python_version >= "3.7" and python_version < "3.8"
dill==0.3.7 ; python_full_version >= "3.7.2" and python_version < "3.8"
distlib==0.3.7 ; python_version >= "3.7" and python_version < "3.8"
distro==1.0.1 ; python_version >= "3.7" and python_version < "3.8"
dns-lexicon==3.14.1 ; python_version >= "3.7" and python_version < "3.8"
dns-lexicon==3.15.1 ; python_version >= "3.7" and python_version < "3.8"
dnspython==1.15.0 ; python_version >= "3.7" and python_version < "3.8"
exceptiongroup==1.1.3 ; python_version >= "3.7" and python_version < "3.8"
execnet==2.0.2 ; python_version >= "3.7" and python_version < "3.8"
@@ -46,19 +46,20 @@ mypy-extensions==1.0.0 ; python_version >= "3.7" and python_version < "3.8"
mypy==1.4.1 ; python_version >= "3.7" and python_version < "3.8"
ndg-httpsclient==0.3.2 ; python_version >= "3.7" and python_version < "3.8"
oauth2client==4.1.3 ; python_version >= "3.7" and python_version < "3.8"
packaging==23.1 ; python_version >= "3.7" and python_version < "3.8"
packaging==23.2 ; python_version >= "3.7" and python_version < "3.8"
parsedatetime==2.4 ; python_version >= "3.7" and python_version < "3.8"
pbr==1.8.0 ; python_version >= "3.7" and python_version < "3.8"
pip==23.2.1 ; python_version >= "3.7" and python_version < "3.8"
platformdirs==3.10.0 ; python_full_version >= "3.7.2" and python_version < "3.8"
pip==23.3 ; python_version >= "3.7" and python_version < "3.8"
platformdirs==3.11.0 ; python_full_version >= "3.7.2" and python_version < "3.8"
pluggy==1.2.0 ; python_version >= "3.7" and python_version < "3.8"
ply==3.4 ; python_version >= "3.7" and python_version < "3.8"
py==1.11.0 ; python_version >= "3.7" and python_version < "3.8"
pyasn1-modules==0.3.0 ; python_version >= "3.7" and python_version < "3.8"
pyasn1==0.4.8 ; python_version >= "3.7" and python_version < "3.8"
pycparser==2.14 ; python_version >= "3.7" and python_version < "3.8"
pylint==2.17.5 ; python_full_version >= "3.7.2" and python_version < "3.8"
pylint==2.17.7 ; python_full_version >= "3.7.2" and python_version < "3.8"
pyopenssl==17.5.0 ; python_version >= "3.7" and python_version < "3.8"
pyotp==2.9.0 ; python_version >= "3.7" and python_version < "3.8"
pyparsing==2.2.1 ; python_version >= "3.7" and python_version < "3.8"
pyrfc3339==1.0 ; python_version >= "3.7" and python_version < "3.8"
pytest-cov==4.1.0 ; python_version >= "3.7" and python_version < "3.8"
@@ -77,7 +78,7 @@ s3transfer==0.3.7 ; python_version >= "3.7" and python_version < "3.8"
setuptools==41.6.0 ; python_version >= "3.7" and python_version < "3.8"
six==1.11.0 ; python_version >= "3.7" and python_version < "3.8"
soupsieve==2.4.1 ; python_version >= "3.7" and python_version < "3.8"
tldextract==3.5.0 ; python_version >= "3.7" and python_version < "3.8"
tldextract==4.0.0 ; python_version >= "3.7" and python_version < "3.8"
tomli==2.0.1 ; python_version < "3.8" and python_version >= "3.7"
tomlkit==0.12.1 ; python_full_version >= "3.7.2" and python_version < "3.8"
tox==1.9.2 ; python_version >= "3.7" and python_version < "3.8"
@@ -87,9 +88,9 @@ types-httplib2==0.22.0.2 ; python_version >= "3.7" and python_version < "3.8"
types-pyopenssl==23.0.0.0 ; python_version >= "3.7" and python_version < "3.8"
types-pyrfc3339==1.1.1.5 ; python_version >= "3.7" and python_version < "3.8"
types-python-dateutil==2.8.19.14 ; python_version >= "3.7" and python_version < "3.8"
types-pytz==2023.3.0.1 ; python_version >= "3.7" and python_version < "3.8"
types-pywin32==306.0.0.4 ; python_version >= "3.7" and python_version < "3.8"
types-requests==2.31.0.2 ; python_version >= "3.7" and python_version < "3.8"
types-pytz==2023.3.1.1 ; python_version >= "3.7" and python_version < "3.8"
types-pywin32==306.0.0.5 ; python_version >= "3.7" and python_version < "3.8"
types-requests==2.31.0.6 ; python_version >= "3.7" and python_version < "3.8"
types-setuptools==68.2.0.0 ; python_version >= "3.7" and python_version < "3.8"
types-six==1.16.21.9 ; python_version >= "3.7" and python_version < "3.8"
types-urllib3==1.26.25.14 ; python_version >= "3.7" and python_version < "3.8"

View File

@@ -54,7 +54,7 @@ cloudflare = "1.5.1"
configobj = "5.0.6"
cryptography = "3.2.1"
distro = "1.0.1"
dns-lexicon = "3.14.1"
dns-lexicon = "3.15.1"
dnspython = "1.15.0"
funcsigs = "0.4"
google-api-python-client = "1.6.5"

View File

@@ -12,35 +12,35 @@ astroid==2.13.5 ; python_full_version >= "3.7.2" and python_version < "4.0"
attrs==23.1.0 ; python_version >= "3.7" and python_version < "4.0"
azure-core==1.29.4 ; python_version >= "3.7" and python_version < "4.0"
azure-devops==7.1.0b3 ; python_version >= "3.7" and python_version < "4.0"
babel==2.12.1 ; python_version >= "3.7" and python_version < "4.0"
babel==2.13.0 ; python_version >= "3.7" and python_version < "4.0"
backcall==0.2.0 ; python_version >= "3.7" and python_version < "4.0"
backports-cached-property==1.0.2 ; python_version >= "3.7" and python_version < "3.8"
bcrypt==4.0.1 ; python_version >= "3.7" and python_version < "4.0"
beautifulsoup4==4.12.2 ; python_version >= "3.7" and python_version < "4.0"
bleach==6.0.0 ; python_version >= "3.7" and python_version < "4.0"
boto3==1.28.45 ; python_version >= "3.7" and python_version < "4.0"
botocore==1.31.45 ; python_version >= "3.7" and python_version < "4.0"
boto3==1.28.66 ; python_version >= "3.7" and python_version < "4.0"
botocore==1.31.66 ; python_version >= "3.7" and python_version < "4.0"
cachecontrol==0.12.14 ; python_version >= "3.7" and python_version < "4.0"
cachetools==5.3.1 ; python_version >= "3.7" and python_version < "4.0"
cachy==0.3.0 ; python_version >= "3.7" and python_version < "4.0"
certifi==2023.7.22 ; python_version >= "3.7" and python_version < "4.0"
cffi==1.15.1 ; python_version >= "3.7" and python_version < "4.0"
charset-normalizer==3.2.0 ; python_version >= "3.7" and python_version < "4.0"
charset-normalizer==3.3.0 ; python_version >= "3.7" and python_version < "4.0"
cleo==1.0.0a5 ; python_version >= "3.7" and python_version < "4.0"
cloudflare==2.11.7 ; python_version >= "3.7" and python_version < "4.0"
cloudflare==2.12.4 ; python_version >= "3.7" and python_version < "4.0"
colorama==0.4.6 ; python_version < "4.0" and sys_platform == "win32" and python_version >= "3.7" or python_version >= "3.7" and python_version < "4.0" and platform_system == "Windows"
configargparse==1.7 ; python_version >= "3.7" and python_version < "4.0"
configobj==5.0.8 ; python_version >= "3.7" and python_version < "4.0"
coverage==7.2.7 ; python_version >= "3.7" and python_version < "4.0"
crashtest==0.3.1 ; python_version >= "3.7" and python_version < "4.0"
cryptography==41.0.3 ; python_version >= "3.7" and python_version < "4.0"
cryptography==41.0.4 ; python_version >= "3.7" and python_version < "4.0"
cython==0.29.36 ; python_version >= "3.7" and python_version < "4.0"
decorator==5.1.1 ; python_version >= "3.7" and python_version < "4.0"
deprecated==1.2.14 ; python_version >= "3.7" and python_version < "4.0"
dill==0.3.7 ; python_full_version >= "3.7.2" and python_version < "4.0"
distlib==0.3.7 ; python_version >= "3.7" and python_version < "4.0"
distro==1.8.0 ; python_version >= "3.7" and python_version < "4.0"
dns-lexicon==3.14.1 ; python_version >= "3.7" and python_version < "4.0"
dns-lexicon==3.15.1 ; python_version >= "3.7" and python_version < "4.0"
dnspython==2.3.0 ; python_version >= "3.7" and python_version < "4.0"
docutils==0.18.1 ; python_version >= "3.7" and python_version < "4.0"
dulwich==0.20.50 ; python_version >= "3.7" and python_version < "4.0"
@@ -48,11 +48,11 @@ exceptiongroup==1.1.3 ; python_version >= "3.7" and python_version < "3.11"
execnet==2.0.2 ; python_version >= "3.7" and python_version < "4.0"
fabric==3.2.2 ; python_version >= "3.7" and python_version < "4.0"
filelock==3.12.2 ; python_version >= "3.7" and python_version < "4.0"
google-api-core==2.11.1 ; python_version >= "3.7" and python_version < "4.0"
google-api-python-client==2.99.0 ; python_version >= "3.7" and python_version < "4.0"
google-api-core==2.12.0 ; python_version >= "3.7" and python_version < "4.0"
google-api-python-client==2.104.0 ; python_version >= "3.7" and python_version < "4.0"
google-auth-httplib2==0.1.1 ; python_version >= "3.7" and python_version < "4.0"
google-auth==2.23.0 ; python_version >= "3.7" and python_version < "4.0"
googleapis-common-protos==1.60.0 ; python_version >= "3.7" and python_version < "4.0"
google-auth==2.23.3 ; python_version >= "3.7" and python_version < "4.0"
googleapis-common-protos==1.61.0 ; python_version >= "3.7" and python_version < "4.0"
html5lib==1.1 ; python_version >= "3.7" and python_version < "4.0"
httplib2==0.22.0 ; python_version >= "3.7" and python_version < "4.0"
idna==3.4 ; python_version >= "3.7" and python_version < "4.0"
@@ -66,7 +66,7 @@ ipython==7.34.0 ; python_version >= "3.7" and python_version < "4.0"
isodate==0.6.1 ; python_version >= "3.7" and python_version < "4.0"
isort==5.11.5 ; python_full_version >= "3.7.2" and python_version < "4.0"
jaraco-classes==3.2.3 ; python_version >= "3.7" and python_version < "4.0"
jedi==0.19.0 ; python_version >= "3.7" and python_version < "4.0"
jedi==0.19.1 ; python_version >= "3.7" and python_version < "4.0"
jeepney==0.8.0 ; python_version >= "3.7" and python_version < "4.0" and sys_platform == "linux"
jinja2==3.1.2 ; python_version >= "3.7" and python_version < "4.0"
jmespath==1.0.1 ; python_version >= "3.7" and python_version < "4.0"
@@ -88,13 +88,13 @@ msrest==0.7.1 ; python_version >= "3.7" and python_version < "4.0"
mypy-extensions==1.0.0 ; python_version >= "3.7" and python_version < "4.0"
mypy==1.4.1 ; python_version >= "3.7" and python_version < "4.0"
oauthlib==3.2.2 ; python_version >= "3.7" and python_version < "4.0"
packaging==23.1 ; python_version >= "3.7" and python_version < "4.0"
packaging==23.2 ; python_version >= "3.7" and python_version < "4.0"
paramiko==3.3.1 ; python_version >= "3.7" and python_version < "4.0"
parsedatetime==2.6 ; python_version >= "3.7" and python_version < "4.0"
parso==0.8.3 ; python_version >= "3.7" and python_version < "4.0"
pexpect==4.8.0 ; python_version >= "3.7" and python_version < "4.0"
pickleshare==0.7.5 ; python_version >= "3.7" and python_version < "4.0"
pip==23.2.1 ; python_version >= "3.7" and python_version < "4.0"
pip==23.3 ; python_version >= "3.7" and python_version < "4.0"
pkginfo==1.9.6 ; python_version >= "3.7" and python_version < "4.0"
pkgutil-resolve-name==1.3.10 ; python_version >= "3.7" and python_version < "3.9"
platformdirs==2.6.2 ; python_version < "4.0" and python_version >= "3.7"
@@ -104,7 +104,7 @@ poetry-core==1.3.2 ; python_version >= "3.7" and python_version < "4.0"
poetry-plugin-export==1.2.0 ; python_version >= "3.7" and python_version < "4.0"
poetry==1.2.2 ; python_version >= "3.7" and python_version < "4.0"
prompt-toolkit==3.0.39 ; python_version >= "3.7" and python_version < "4.0"
protobuf==4.24.3 ; python_version >= "3.7" and python_version < "4.0"
protobuf==4.24.4 ; python_version >= "3.7" and python_version < "4.0"
ptyprocess==0.7.0 ; python_version >= "3.7" and python_version < "4.0"
py==1.11.0 ; python_version >= "3.7" and python_version < "4.0"
pyasn1-modules==0.3.0 ; python_version >= "3.7" and python_version < "4.0"
@@ -116,6 +116,7 @@ pylint==2.15.5 ; python_full_version >= "3.7.2" and python_version < "4.0"
pynacl==1.5.0 ; python_version >= "3.7" and python_version < "4.0"
pynsist==2.7 ; python_version >= "3.7" and python_version < "4.0"
pyopenssl==23.2.0 ; python_version >= "3.7" and python_version < "4.0"
pyotp==2.9.0 ; python_version >= "3.7" and python_version < "4.0"
pyparsing==3.1.1 ; python_version >= "3.7" and python_version < "4.0"
pyrfc3339==1.1 ; python_version >= "3.7" and python_version < "4.0"
pyrsistent==0.19.3 ; python_version >= "3.7" and python_version < "4.0"
@@ -136,9 +137,9 @@ requests-oauthlib==1.3.1 ; python_version >= "3.7" and python_version < "4.0"
requests-toolbelt==0.9.1 ; python_version >= "3.7" and python_version < "4.0"
requests==2.31.0 ; python_version >= "3.7" and python_version < "4.0"
rfc3986==2.0.0 ; python_version >= "3.7" and python_version < "4.0"
rich==13.5.2 ; python_version >= "3.7" and python_version < "4.0"
rich==13.6.0 ; python_version >= "3.7" and python_version < "4.0"
rsa==4.9 ; python_version >= "3.7" and python_version < "4"
s3transfer==0.6.2 ; python_version >= "3.7" and python_version < "4.0"
s3transfer==0.7.0 ; python_version >= "3.7" and python_version < "4.0"
secretstorage==3.3.3 ; python_version >= "3.7" and python_version < "4.0" and sys_platform == "linux"
semantic-version==2.10.0 ; python_version >= "3.7" and python_version < "4.0"
setuptools-rust==1.7.0 ; python_version >= "3.7" and python_version < "4.0"
@@ -156,7 +157,7 @@ sphinxcontrib-jquery==4.1 ; python_version >= "3.7" and python_version < "4.0"
sphinxcontrib-jsmath==1.0.1 ; python_version >= "3.7" and python_version < "4.0"
sphinxcontrib-qthelp==1.0.3 ; python_version >= "3.7" and python_version < "4.0"
sphinxcontrib-serializinghtml==1.1.5 ; python_version >= "3.7" and python_version < "4.0"
tldextract==3.5.0 ; python_version >= "3.7" and python_version < "4.0"
tldextract==4.0.0 ; python_version >= "3.7" and python_version < "4.0"
tomli==2.0.1 ; python_version >= "3.7" and python_full_version <= "3.11.0a6"
tomlkit==0.12.1 ; python_version < "4.0" and python_version >= "3.7"
tox==3.28.0 ; python_version >= "3.7" and python_version < "4.0"
@@ -167,17 +168,17 @@ types-httplib2==0.22.0.2 ; python_version >= "3.7" and python_version < "4.0"
types-pyopenssl==23.2.0.2 ; python_version >= "3.7" and python_version < "4.0"
types-pyrfc3339==1.1.1.5 ; python_version >= "3.7" and python_version < "4.0"
types-python-dateutil==2.8.19.14 ; python_version >= "3.7" and python_version < "4.0"
types-pytz==2023.3.0.1 ; python_version >= "3.7" and python_version < "4.0"
types-pywin32==306.0.0.4 ; python_version >= "3.7" and python_version < "4.0"
types-requests==2.31.0.2 ; python_version >= "3.7" and python_version < "4.0"
types-pytz==2023.3.1.1 ; python_version >= "3.7" and python_version < "4.0"
types-pywin32==306.0.0.5 ; python_version >= "3.7" and python_version < "4.0"
types-requests==2.31.0.6 ; python_version >= "3.7" and python_version < "4.0"
types-setuptools==68.2.0.0 ; python_version >= "3.7" and python_version < "4.0"
types-six==1.16.21.9 ; python_version >= "3.7" and python_version < "4.0"
types-urllib3==1.26.25.14 ; python_version >= "3.7" and python_version < "4.0"
typing-extensions==4.7.1 ; python_version >= "3.7" and python_version < "4.0"
uritemplate==4.1.1 ; python_version >= "3.7" and python_version < "4.0"
urllib3==1.26.16 ; python_version >= "3.7" and python_version < "4.0"
urllib3==1.26.18 ; python_version < "4.0" and python_version >= "3.7"
virtualenv==20.21.1 ; python_version >= "3.7" and python_version < "4.0"
wcwidth==0.2.6 ; python_version >= "3.7" and python_version < "4.0"
wcwidth==0.2.8 ; python_version >= "3.7" and python_version < "4.0"
webencodings==0.5.1 ; python_version >= "3.7" and python_version < "4.0"
wheel==0.41.2 ; python_version >= "3.7" and python_version < "4.0"
wrapt==1.15.0 ; python_version < "4.0" and python_version >= "3.7"