From 43474762b24e285bc525d9ffa09c6f7658525353 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Skytt=C3=A4?= Date: Mon, 4 Jan 2021 12:47:29 +0200 Subject: [PATCH] Drop remaining Python < 3.8 support (#44743) Co-authored-by: Paulus Schoutsen Co-authored-by: Franck Nijhof --- .pre-commit-config.yaml | 2 +- .readthedocs.yml | 2 +- azure-pipelines-release.yml | 4 ++-- azure-pipelines-translation.yml | 4 ++-- homeassistant/bootstrap.py | 10 ++++---- homeassistant/core.py | 2 -- homeassistant/package_constraints.txt | 1 - homeassistant/runner.py | 10 +------- homeassistant/util/package.py | 12 +--------- homeassistant/util/thread.py | 23 ------------------- pyproject.toml | 2 +- requirements.txt | 1 - setup.cfg | 5 ++-- setup.py | 1 - tests/components/plex/mock_classes.py | 2 +- tests/components/webostv/test_media_player.py | 9 ++------ tox.ini | 2 +- 17 files changed, 20 insertions(+), 72 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 11cd4aa7731f..087dc9140353 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -3,7 +3,7 @@ repos: rev: v2.7.2 hooks: - id: pyupgrade - args: [--py37-plus] + args: [--py38-plus] - repo: https://github.com/psf/black rev: 20.8b1 hooks: diff --git a/.readthedocs.yml b/.readthedocs.yml index 0303f84d51c1..e8344e0a655c 100644 --- a/.readthedocs.yml +++ b/.readthedocs.yml @@ -4,7 +4,7 @@ build: image: latest python: - version: 3.7 + version: 3.8 setup_py_install: true requirements_file: requirements_docs.txt diff --git a/azure-pipelines-release.yml b/azure-pipelines-release.yml index 6da0b128e475..418fdf5b26c5 100644 --- a/azure-pipelines-release.yml +++ b/azure-pipelines-release.yml @@ -60,9 +60,9 @@ stages: vmImage: 'ubuntu-latest' steps: - task: UsePythonVersion@0 - displayName: 'Use Python 3.7' + displayName: 'Use Python 3.8' inputs: - versionSpec: '3.7' + versionSpec: '3.8' - script: pip install twine wheel displayName: 'Install tools' - script: python setup.py sdist bdist_wheel diff --git a/azure-pipelines-translation.yml b/azure-pipelines-translation.yml index 9f4db8d2005d..481b98bc4840 100644 --- a/azure-pipelines-translation.yml +++ b/azure-pipelines-translation.yml @@ -30,9 +30,9 @@ jobs: vmImage: 'ubuntu-latest' steps: - task: UsePythonVersion@0 - displayName: 'Use Python 3.7' + displayName: 'Use Python 3.8' inputs: - versionSpec: '3.7' + versionSpec: '3.8' - script: | export LOKALISE_TOKEN="$(lokaliseToken)" export AZURE_BRANCH="$(Build.SourceBranchName)" diff --git a/homeassistant/bootstrap.py b/homeassistant/bootstrap.py index ff8ecfa0070a..bf16c4091f1d 100644 --- a/homeassistant/bootstrap.py +++ b/homeassistant/bootstrap.py @@ -307,12 +307,10 @@ def async_enable_logging( sys.excepthook = lambda *args: logging.getLogger(None).exception( "Uncaught exception", exc_info=args # type: ignore ) - - if sys.version_info[:2] >= (3, 8): - threading.excepthook = lambda args: logging.getLogger(None).exception( - "Uncaught thread exception", - exc_info=(args.exc_type, args.exc_value, args.exc_traceback), - ) + threading.excepthook = lambda args: logging.getLogger(None).exception( + "Uncaught thread exception", + exc_info=(args.exc_type, args.exc_value, args.exc_traceback), # type: ignore[arg-type] + ) # Log errors to a file if we have write access to file or config dir if log_file is None: diff --git a/homeassistant/core.py b/homeassistant/core.py index 6b657f600d85..18b69fd5366f 100644 --- a/homeassistant/core.py +++ b/homeassistant/core.py @@ -73,7 +73,6 @@ from homeassistant.exceptions import ( from homeassistant.util import location, network from homeassistant.util.async_ import fire_coroutine_threadsafe, run_callback_threadsafe import homeassistant.util.dt as dt_util -from homeassistant.util.thread import fix_threading_exception_logging from homeassistant.util.timeout import TimeoutManager from homeassistant.util.unit_system import IMPERIAL_SYSTEM, METRIC_SYSTEM, UnitSystem import homeassistant.util.uuid as uuid_util @@ -86,7 +85,6 @@ if TYPE_CHECKING: block_async_io.enable() -fix_threading_exception_logging() T = TypeVar("T") _UNDEF: dict = {} # Internal; not helpers.typing.UNDEFINED due to circular dependency diff --git a/homeassistant/package_constraints.txt b/homeassistant/package_constraints.txt index d273d730b974..06f2c5a67043 100644 --- a/homeassistant/package_constraints.txt +++ b/homeassistant/package_constraints.txt @@ -15,7 +15,6 @@ emoji==0.5.4 hass-nabucasa==0.39.0 home-assistant-frontend==20201229.0 httpx==0.16.1 -importlib-metadata==1.6.0;python_version<'3.8' jinja2>=2.11.2 netdisco==2.8.2 paho-mqtt==1.5.1 diff --git a/homeassistant/runner.py b/homeassistant/runner.py index 0f8bb836da5b..54d20a7deffb 100644 --- a/homeassistant/runner.py +++ b/homeassistant/runner.py @@ -3,7 +3,6 @@ import asyncio from concurrent.futures import ThreadPoolExecutor import dataclasses import logging -import sys from typing import Any, Dict, Optional from homeassistant import bootstrap @@ -41,14 +40,7 @@ class RuntimeConfig: open_ui: bool = False -# In Python 3.8+ proactor policy is the default on Windows -if sys.platform == "win32" and sys.version_info[:2] < (3, 8): - PolicyBase = asyncio.WindowsProactorEventLoopPolicy -else: - PolicyBase = asyncio.DefaultEventLoopPolicy - - -class HassEventLoopPolicy(PolicyBase): # type: ignore +class HassEventLoopPolicy(asyncio.DefaultEventLoopPolicy): # type: ignore[valid-type,misc] """Event loop policy for Home Assistant.""" def __init__(self, debug: bool) -> None: diff --git a/homeassistant/util/package.py b/homeassistant/util/package.py index a665fd78914a..5391d92ed89c 100644 --- a/homeassistant/util/package.py +++ b/homeassistant/util/package.py @@ -1,5 +1,6 @@ """Helpers to install PyPi packages.""" import asyncio +from importlib.metadata import PackageNotFoundError, version import logging import os from pathlib import Path @@ -10,17 +11,6 @@ from urllib.parse import urlparse import pkg_resources -if sys.version_info[:2] >= (3, 8): - from importlib.metadata import ( # pylint: disable=no-name-in-module,import-error - PackageNotFoundError, - version, - ) -else: - from importlib_metadata import ( # pylint: disable=import-error - PackageNotFoundError, - version, - ) - _LOGGER = logging.getLogger(__name__) diff --git a/homeassistant/util/thread.py b/homeassistant/util/thread.py index bf61c67172ad..7743e1d159c2 100644 --- a/homeassistant/util/thread.py +++ b/homeassistant/util/thread.py @@ -1,33 +1,10 @@ """Threading util helpers.""" import ctypes import inspect -import sys import threading from typing import Any -def fix_threading_exception_logging() -> None: - """Fix threads passing uncaught exceptions to our exception hook. - - https://bugs.python.org/issue1230540 - Fixed in Python 3.8. - """ - if sys.version_info[:2] >= (3, 8): - return - - run_old = threading.Thread.run - - def run(*args: Any, **kwargs: Any) -> None: - try: - run_old(*args, **kwargs) - except (KeyboardInterrupt, SystemExit): # pylint: disable=try-except-raise - raise - except Exception: # pylint: disable=broad-except - sys.excepthook(*sys.exc_info()) - - threading.Thread.run = run # type: ignore - - def _async_raise(tid: int, exctype: Any) -> None: """Raise an exception in the threads with id tid.""" if not inspect.isclass(exctype): diff --git a/pyproject.toml b/pyproject.toml index 0f416d9e0141..445f13e87249 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,5 +1,5 @@ [tool.black] -target-version = ["py37", "py38"] +target-version = ["py38"] exclude = 'generated' [tool.isort] diff --git a/requirements.txt b/requirements.txt index 7492e7941726..d566cb738aef 100644 --- a/requirements.txt +++ b/requirements.txt @@ -9,7 +9,6 @@ bcrypt==3.1.7 certifi>=2020.12.5 ciso8601==2.1.3 httpx==0.16.1 -importlib-metadata==1.6.0;python_version<'3.8' jinja2>=2.11.2 PyJWT==1.7.1 cryptography==3.2 diff --git a/setup.cfg b/setup.cfg index de5092dcecfa..1fc973ef21c9 100644 --- a/setup.cfg +++ b/setup.cfg @@ -11,7 +11,8 @@ classifier = Intended Audience :: Developers License :: OSI Approved :: Apache Software License Operating System :: OS Independent - Programming Language :: Python :: 3.7 + Programming Language :: Python :: 3.8 + Programming Language :: Python :: 3.9 Topic :: Home Automation [flake8] @@ -31,7 +32,7 @@ ignore = W504 [mypy] -python_version = 3.7 +python_version = 3.8 show_error_codes = true ignore_errors = true follow_imports = silent diff --git a/setup.py b/setup.py index 59ea906344c1..82d6efacb1bc 100755 --- a/setup.py +++ b/setup.py @@ -40,7 +40,6 @@ REQUIRES = [ "certifi>=2020.12.5", "ciso8601==2.1.3", "httpx==0.16.1", - "importlib-metadata==1.6.0;python_version<'3.8'", "jinja2>=2.11.2", "PyJWT==1.7.1", # PyJWT has loose dependency. We want the latest one. diff --git a/tests/components/plex/mock_classes.py b/tests/components/plex/mock_classes.py index 8ac894438be4..5f2fad6a8f1c 100644 --- a/tests/components/plex/mock_classes.py +++ b/tests/components/plex/mock_classes.py @@ -247,7 +247,7 @@ class MockPlexServer: """Mock the playlist lookup method.""" return MockPlexMediaItem(playlist, mediatype="playlist") - @lru_cache() + @lru_cache def playlists(self): """Mock the playlists lookup method with a lazy init.""" return [ diff --git a/tests/components/webostv/test_media_player.py b/tests/components/webostv/test_media_player.py index 8ddc7b316575..70bc82746848 100644 --- a/tests/components/webostv/test_media_player.py +++ b/tests/components/webostv/test_media_player.py @@ -1,5 +1,6 @@ """The tests for the LG webOS media player platform.""" -import sys + +from unittest.mock import patch import pytest @@ -25,12 +26,6 @@ from homeassistant.const import ( ) from homeassistant.setup import async_setup_component -if sys.version_info >= (3, 8, 0): - from unittest.mock import patch -else: - from unittest.mock import patch - - NAME = "fake" ENTITY_ID = f"{media_player.DOMAIN}.{NAME}" diff --git a/tox.ini b/tox.ini index cc1df307bfe4..9c9963c28eed 100644 --- a/tox.ini +++ b/tox.ini @@ -1,5 +1,5 @@ [tox] -envlist = py37, py38, lint, pylint, typing, cov +envlist = py38, py39, lint, pylint, typing, cov skip_missing_interpreters = True ignore_basepython_conflict = True