From 5102d1a5f3d628673a7df9c18503a09812a36d04 Mon Sep 17 00:00:00 2001 From: Franck Nijhof Date: Sun, 22 Jan 2023 20:40:33 +0100 Subject: [PATCH] Drop Python 3.9 support (#85456) --- .github/workflows/builder.yml | 2 +- .github/workflows/ci.yaml | 4 +-- .github/workflows/translations.yaml | 2 +- Dockerfile.dev | 2 +- homeassistant/components/lirc/__init__.py | 2 +- .../components/radiotherm/__init__.py | 6 ++--- .../components/radiotherm/coordinator.py | 6 ++--- .../components/websocket_api/http.py | 2 ++ homeassistant/const.py | 4 +-- mypy.ini | 2 +- pyproject.toml | 3 +-- requirements_test.txt | 1 - script/hassfest/requirements.py | 26 +++++-------------- 13 files changed, 24 insertions(+), 38 deletions(-) diff --git a/.github/workflows/builder.yml b/.github/workflows/builder.yml index 651f8a78993..c3a0a721710 100644 --- a/.github/workflows/builder.yml +++ b/.github/workflows/builder.yml @@ -10,7 +10,7 @@ on: env: BUILD_TYPE: core - DEFAULT_PYTHON: 3.9 + DEFAULT_PYTHON: "3.10" jobs: init: diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 53cd8dd39b2..ccfef6244be 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -31,8 +31,8 @@ env: CACHE_VERSION: 3 PIP_CACHE_VERSION: 3 HA_SHORT_VERSION: 2023.2 - DEFAULT_PYTHON: 3.9 - ALL_PYTHON_VERSIONS: "['3.9', '3.10']" + DEFAULT_PYTHON: "3.10" + ALL_PYTHON_VERSIONS: "['3.10']" PRE_COMMIT_CACHE: ~/.cache/pre-commit PIP_CACHE: /tmp/pip-cache SQLALCHEMY_WARN_20: 1 diff --git a/.github/workflows/translations.yaml b/.github/workflows/translations.yaml index 0c895ee006e..e96cb415d67 100644 --- a/.github/workflows/translations.yaml +++ b/.github/workflows/translations.yaml @@ -12,7 +12,7 @@ on: - "**strings.json" env: - DEFAULT_PYTHON: 3.9 + DEFAULT_PYTHON: "3.10" jobs: upload: diff --git a/Dockerfile.dev b/Dockerfile.dev index fc9843461a0..863ac5690bc 100644 --- a/Dockerfile.dev +++ b/Dockerfile.dev @@ -1,4 +1,4 @@ -FROM mcr.microsoft.com/vscode/devcontainers/python:0-3.9 +FROM mcr.microsoft.com/vscode/devcontainers/python:0-3.10 SHELL ["/bin/bash", "-o", "pipefail", "-c"] diff --git a/homeassistant/components/lirc/__init__.py b/homeassistant/components/lirc/__init__.py index cca7593768b..227d1e7d5a9 100644 --- a/homeassistant/components/lirc/__init__.py +++ b/homeassistant/components/lirc/__init__.py @@ -60,7 +60,7 @@ class LircInterface(threading.Thread): def run(self): """Run the loop of the LIRC interface thread.""" _LOGGER.debug("LIRC interface thread started") - while not self.stopped.isSet(): + while not self.stopped.is_set(): try: code = lirc.nextcode() # list; empty if no buttons pressed except lirc.NextCodeError: diff --git a/homeassistant/components/radiotherm/__init__.py b/homeassistant/components/radiotherm/__init__.py index 787570eaeb4..808ee56b092 100644 --- a/homeassistant/components/radiotherm/__init__.py +++ b/homeassistant/components/radiotherm/__init__.py @@ -32,12 +32,12 @@ async def _async_call_or_raise_not_ready( except RadiothermTstatError as ex: msg = f"{host} was busy (invalid value returned): {ex}" raise ConfigEntryNotReady(msg) from ex - except (OSError, URLError) as ex: - msg = f"{host} connection error: {ex}" - raise ConfigEntryNotReady(msg) from ex except timeout as ex: msg = f"{host} timed out waiting for a response: {ex}" raise ConfigEntryNotReady(msg) from ex + except (OSError, URLError) as ex: + msg = f"{host} connection error: {ex}" + raise ConfigEntryNotReady(msg) from ex async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: diff --git a/homeassistant/components/radiotherm/coordinator.py b/homeassistant/components/radiotherm/coordinator.py index 91acdee8710..ffc6bfcc8ba 100644 --- a/homeassistant/components/radiotherm/coordinator.py +++ b/homeassistant/components/radiotherm/coordinator.py @@ -39,9 +39,9 @@ class RadioThermUpdateCoordinator(DataUpdateCoordinator[RadioThermUpdate]): except RadiothermTstatError as ex: msg = f"{self._description} was busy (invalid value returned): {ex}" raise UpdateFailed(msg) from ex - except (OSError, URLError) as ex: - msg = f"{self._description} connection error: {ex}" - raise UpdateFailed(msg) from ex except timeout as ex: msg = f"{self._description}) timed out waiting for a response: {ex}" raise UpdateFailed(msg) from ex + except (OSError, URLError) as ex: + msg = f"{self._description} connection error: {ex}" + raise UpdateFailed(msg) from ex diff --git a/homeassistant/components/websocket_api/http.py b/homeassistant/components/websocket_api/http.py index 7a08d19d857..e33e1cc3ce8 100644 --- a/homeassistant/components/websocket_api/http.py +++ b/homeassistant/components/websocket_api/http.py @@ -57,6 +57,8 @@ class WebSocketAdapter(logging.LoggerAdapter): def process(self, msg: str, kwargs: Any) -> tuple[str, Any]: """Add connid to websocket log messages.""" + if not self.extra or "connid" not in self.extra: + return msg, kwargs return f'[{self.extra["connid"]}] {msg}', kwargs diff --git a/homeassistant/const.py b/homeassistant/const.py index 8337f1d7e23..4be0be42f76 100644 --- a/homeassistant/const.py +++ b/homeassistant/const.py @@ -11,10 +11,10 @@ MINOR_VERSION: Final = 2 PATCH_VERSION: Final = "0.dev0" __short_version__: Final = f"{MAJOR_VERSION}.{MINOR_VERSION}" __version__: Final = f"{__short_version__}.{PATCH_VERSION}" -REQUIRED_PYTHON_VER: Final[tuple[int, int, int]] = (3, 9, 0) +REQUIRED_PYTHON_VER: Final[tuple[int, int, int]] = (3, 10, 0) REQUIRED_NEXT_PYTHON_VER: Final[tuple[int, int, int]] = (3, 10, 0) # Truthy date string triggers showing related deprecation warning messages. -REQUIRED_NEXT_PYTHON_HA_RELEASE: Final = "2023.2" +REQUIRED_NEXT_PYTHON_HA_RELEASE: Final = "" # Format for platform files PLATFORM_FORMAT: Final = "{platform}.{domain}" diff --git a/mypy.ini b/mypy.ini index 7da024bd3c1..b60fb346008 100644 --- a/mypy.ini +++ b/mypy.ini @@ -3,7 +3,7 @@ # To update, run python3 -m script.hassfest -p mypy_config [mypy] -python_version = 3.9 +python_version = 3.10 show_error_codes = true follow_imports = silent ignore_missing_imports = true diff --git a/pyproject.toml b/pyproject.toml index 7e417f4c85c..a927ab18863 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -18,11 +18,10 @@ classifiers = [ "Intended Audience :: Developers", "License :: OSI Approved :: Apache Software License", "Operating System :: OS Independent", - "Programming Language :: Python :: 3.9", "Programming Language :: Python :: 3.10", "Topic :: Home Automation", ] -requires-python = ">=3.9.0" +requires-python = ">=3.10.0" dependencies = [ "aiohttp==3.8.1", "astral==2.2", diff --git a/requirements_test.txt b/requirements_test.txt index 227477c8667..183efcd3e8c 100644 --- a/requirements_test.txt +++ b/requirements_test.txt @@ -30,7 +30,6 @@ pytest-xdist==2.5.0 pytest==7.2.1 requests_mock==1.10.0 respx==0.20.1 -stdlib-list==0.7.0 tomli==2.0.1;python_version<"3.11" tqdm==4.64.0 types-atomicwrites==1.4.1 diff --git a/script/hassfest/requirements.py b/script/hassfest/requirements.py index 27dd0654dc6..8e4ac524b2f 100644 --- a/script/hassfest/requirements.py +++ b/script/hassfest/requirements.py @@ -11,10 +11,8 @@ import sys from typing import Any from awesomeversion import AwesomeVersion, AwesomeVersionStrategy -from stdlib_list import stdlib_list from tqdm import tqdm -from homeassistant.const import REQUIRED_NEXT_PYTHON_VER, REQUIRED_PYTHON_VER import homeassistant.util.package as pkg_util from script.gen_requirements_all import COMMENT_REQUIREMENTS, normalize_package_name @@ -28,17 +26,6 @@ PACKAGE_REGEX = re.compile( ) PIP_REGEX = re.compile(r"^(--.+\s)?([-_\.\w\d]+.*(?:==|>=|<=|~=|!=|<|>|===)?.*$)") PIP_VERSION_RANGE_SEPARATOR = re.compile(r"^(==|>=|<=|~=|!=|<|>|===)?(.*)$") -SUPPORTED_PYTHON_TUPLES = [ - REQUIRED_PYTHON_VER[:2], -] -if REQUIRED_PYTHON_VER[0] == REQUIRED_NEXT_PYTHON_VER[0]: - for minor in range(REQUIRED_PYTHON_VER[1] + 1, REQUIRED_NEXT_PYTHON_VER[1] + 1): - if minor < 10: # stdlib list does not support 3.10+ - SUPPORTED_PYTHON_TUPLES.append((REQUIRED_PYTHON_VER[0], minor)) -SUPPORTED_PYTHON_VERSIONS = [ - ".".join(map(str, version_tuple)) for version_tuple in SUPPORTED_PYTHON_TUPLES -] -STD_LIBS = {version: set(stdlib_list(version)) for version in SUPPORTED_PYTHON_VERSIONS} IGNORE_VIOLATIONS = { # Still has standard library requirements. @@ -161,13 +148,12 @@ def validate_requirements(integration: Integration) -> None: return # Check for requirements incompatible with standard library. - for version, std_libs in STD_LIBS.items(): - for req in all_integration_requirements: - if req in std_libs: - integration.add_error( - "requirements", - f"Package {req} is not compatible with Python {version} standard library", - ) + for req in all_integration_requirements: + if req in sys.stlib_module_names: + integration.add_error( + "requirements", + f"Package {req} is not compatible with the Python standard library", + ) @cache