Drop remaining Python < 3.8 support (#44743)
Co-authored-by: Paulus Schoutsen <paulus@home-assistant.io> Co-authored-by: Franck Nijhof <git@frenck.dev>
This commit is contained in:
parent
134db3f710
commit
43474762b2
17 changed files with 20 additions and 72 deletions
|
@ -3,7 +3,7 @@ repos:
|
||||||
rev: v2.7.2
|
rev: v2.7.2
|
||||||
hooks:
|
hooks:
|
||||||
- id: pyupgrade
|
- id: pyupgrade
|
||||||
args: [--py37-plus]
|
args: [--py38-plus]
|
||||||
- repo: https://github.com/psf/black
|
- repo: https://github.com/psf/black
|
||||||
rev: 20.8b1
|
rev: 20.8b1
|
||||||
hooks:
|
hooks:
|
||||||
|
|
|
@ -4,7 +4,7 @@ build:
|
||||||
image: latest
|
image: latest
|
||||||
|
|
||||||
python:
|
python:
|
||||||
version: 3.7
|
version: 3.8
|
||||||
setup_py_install: true
|
setup_py_install: true
|
||||||
|
|
||||||
requirements_file: requirements_docs.txt
|
requirements_file: requirements_docs.txt
|
||||||
|
|
|
@ -60,9 +60,9 @@ stages:
|
||||||
vmImage: 'ubuntu-latest'
|
vmImage: 'ubuntu-latest'
|
||||||
steps:
|
steps:
|
||||||
- task: UsePythonVersion@0
|
- task: UsePythonVersion@0
|
||||||
displayName: 'Use Python 3.7'
|
displayName: 'Use Python 3.8'
|
||||||
inputs:
|
inputs:
|
||||||
versionSpec: '3.7'
|
versionSpec: '3.8'
|
||||||
- script: pip install twine wheel
|
- script: pip install twine wheel
|
||||||
displayName: 'Install tools'
|
displayName: 'Install tools'
|
||||||
- script: python setup.py sdist bdist_wheel
|
- script: python setup.py sdist bdist_wheel
|
||||||
|
|
|
@ -30,9 +30,9 @@ jobs:
|
||||||
vmImage: 'ubuntu-latest'
|
vmImage: 'ubuntu-latest'
|
||||||
steps:
|
steps:
|
||||||
- task: UsePythonVersion@0
|
- task: UsePythonVersion@0
|
||||||
displayName: 'Use Python 3.7'
|
displayName: 'Use Python 3.8'
|
||||||
inputs:
|
inputs:
|
||||||
versionSpec: '3.7'
|
versionSpec: '3.8'
|
||||||
- script: |
|
- script: |
|
||||||
export LOKALISE_TOKEN="$(lokaliseToken)"
|
export LOKALISE_TOKEN="$(lokaliseToken)"
|
||||||
export AZURE_BRANCH="$(Build.SourceBranchName)"
|
export AZURE_BRANCH="$(Build.SourceBranchName)"
|
||||||
|
|
|
@ -307,12 +307,10 @@ def async_enable_logging(
|
||||||
sys.excepthook = lambda *args: logging.getLogger(None).exception(
|
sys.excepthook = lambda *args: logging.getLogger(None).exception(
|
||||||
"Uncaught exception", exc_info=args # type: ignore
|
"Uncaught exception", exc_info=args # type: ignore
|
||||||
)
|
)
|
||||||
|
threading.excepthook = lambda args: logging.getLogger(None).exception(
|
||||||
if sys.version_info[:2] >= (3, 8):
|
"Uncaught thread exception",
|
||||||
threading.excepthook = lambda args: logging.getLogger(None).exception(
|
exc_info=(args.exc_type, args.exc_value, args.exc_traceback), # type: ignore[arg-type]
|
||||||
"Uncaught thread exception",
|
)
|
||||||
exc_info=(args.exc_type, args.exc_value, args.exc_traceback),
|
|
||||||
)
|
|
||||||
|
|
||||||
# Log errors to a file if we have write access to file or config dir
|
# Log errors to a file if we have write access to file or config dir
|
||||||
if log_file is None:
|
if log_file is None:
|
||||||
|
|
|
@ -73,7 +73,6 @@ from homeassistant.exceptions import (
|
||||||
from homeassistant.util import location, network
|
from homeassistant.util import location, network
|
||||||
from homeassistant.util.async_ import fire_coroutine_threadsafe, run_callback_threadsafe
|
from homeassistant.util.async_ import fire_coroutine_threadsafe, run_callback_threadsafe
|
||||||
import homeassistant.util.dt as dt_util
|
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.timeout import TimeoutManager
|
||||||
from homeassistant.util.unit_system import IMPERIAL_SYSTEM, METRIC_SYSTEM, UnitSystem
|
from homeassistant.util.unit_system import IMPERIAL_SYSTEM, METRIC_SYSTEM, UnitSystem
|
||||||
import homeassistant.util.uuid as uuid_util
|
import homeassistant.util.uuid as uuid_util
|
||||||
|
@ -86,7 +85,6 @@ if TYPE_CHECKING:
|
||||||
|
|
||||||
|
|
||||||
block_async_io.enable()
|
block_async_io.enable()
|
||||||
fix_threading_exception_logging()
|
|
||||||
|
|
||||||
T = TypeVar("T")
|
T = TypeVar("T")
|
||||||
_UNDEF: dict = {} # Internal; not helpers.typing.UNDEFINED due to circular dependency
|
_UNDEF: dict = {} # Internal; not helpers.typing.UNDEFINED due to circular dependency
|
||||||
|
|
|
@ -15,7 +15,6 @@ emoji==0.5.4
|
||||||
hass-nabucasa==0.39.0
|
hass-nabucasa==0.39.0
|
||||||
home-assistant-frontend==20201229.0
|
home-assistant-frontend==20201229.0
|
||||||
httpx==0.16.1
|
httpx==0.16.1
|
||||||
importlib-metadata==1.6.0;python_version<'3.8'
|
|
||||||
jinja2>=2.11.2
|
jinja2>=2.11.2
|
||||||
netdisco==2.8.2
|
netdisco==2.8.2
|
||||||
paho-mqtt==1.5.1
|
paho-mqtt==1.5.1
|
||||||
|
|
|
@ -3,7 +3,6 @@ import asyncio
|
||||||
from concurrent.futures import ThreadPoolExecutor
|
from concurrent.futures import ThreadPoolExecutor
|
||||||
import dataclasses
|
import dataclasses
|
||||||
import logging
|
import logging
|
||||||
import sys
|
|
||||||
from typing import Any, Dict, Optional
|
from typing import Any, Dict, Optional
|
||||||
|
|
||||||
from homeassistant import bootstrap
|
from homeassistant import bootstrap
|
||||||
|
@ -41,14 +40,7 @@ class RuntimeConfig:
|
||||||
open_ui: bool = False
|
open_ui: bool = False
|
||||||
|
|
||||||
|
|
||||||
# In Python 3.8+ proactor policy is the default on Windows
|
class HassEventLoopPolicy(asyncio.DefaultEventLoopPolicy): # type: ignore[valid-type,misc]
|
||||||
if sys.platform == "win32" and sys.version_info[:2] < (3, 8):
|
|
||||||
PolicyBase = asyncio.WindowsProactorEventLoopPolicy
|
|
||||||
else:
|
|
||||||
PolicyBase = asyncio.DefaultEventLoopPolicy
|
|
||||||
|
|
||||||
|
|
||||||
class HassEventLoopPolicy(PolicyBase): # type: ignore
|
|
||||||
"""Event loop policy for Home Assistant."""
|
"""Event loop policy for Home Assistant."""
|
||||||
|
|
||||||
def __init__(self, debug: bool) -> None:
|
def __init__(self, debug: bool) -> None:
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
"""Helpers to install PyPi packages."""
|
"""Helpers to install PyPi packages."""
|
||||||
import asyncio
|
import asyncio
|
||||||
|
from importlib.metadata import PackageNotFoundError, version
|
||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
@ -10,17 +11,6 @@ from urllib.parse import urlparse
|
||||||
|
|
||||||
import pkg_resources
|
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__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,33 +1,10 @@
|
||||||
"""Threading util helpers."""
|
"""Threading util helpers."""
|
||||||
import ctypes
|
import ctypes
|
||||||
import inspect
|
import inspect
|
||||||
import sys
|
|
||||||
import threading
|
import threading
|
||||||
from typing import Any
|
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:
|
def _async_raise(tid: int, exctype: Any) -> None:
|
||||||
"""Raise an exception in the threads with id tid."""
|
"""Raise an exception in the threads with id tid."""
|
||||||
if not inspect.isclass(exctype):
|
if not inspect.isclass(exctype):
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
[tool.black]
|
[tool.black]
|
||||||
target-version = ["py37", "py38"]
|
target-version = ["py38"]
|
||||||
exclude = 'generated'
|
exclude = 'generated'
|
||||||
|
|
||||||
[tool.isort]
|
[tool.isort]
|
||||||
|
|
|
@ -9,7 +9,6 @@ bcrypt==3.1.7
|
||||||
certifi>=2020.12.5
|
certifi>=2020.12.5
|
||||||
ciso8601==2.1.3
|
ciso8601==2.1.3
|
||||||
httpx==0.16.1
|
httpx==0.16.1
|
||||||
importlib-metadata==1.6.0;python_version<'3.8'
|
|
||||||
jinja2>=2.11.2
|
jinja2>=2.11.2
|
||||||
PyJWT==1.7.1
|
PyJWT==1.7.1
|
||||||
cryptography==3.2
|
cryptography==3.2
|
||||||
|
|
|
@ -11,7 +11,8 @@ classifier =
|
||||||
Intended Audience :: Developers
|
Intended Audience :: Developers
|
||||||
License :: OSI Approved :: Apache Software License
|
License :: OSI Approved :: Apache Software License
|
||||||
Operating System :: OS Independent
|
Operating System :: OS Independent
|
||||||
Programming Language :: Python :: 3.7
|
Programming Language :: Python :: 3.8
|
||||||
|
Programming Language :: Python :: 3.9
|
||||||
Topic :: Home Automation
|
Topic :: Home Automation
|
||||||
|
|
||||||
[flake8]
|
[flake8]
|
||||||
|
@ -31,7 +32,7 @@ ignore =
|
||||||
W504
|
W504
|
||||||
|
|
||||||
[mypy]
|
[mypy]
|
||||||
python_version = 3.7
|
python_version = 3.8
|
||||||
show_error_codes = true
|
show_error_codes = true
|
||||||
ignore_errors = true
|
ignore_errors = true
|
||||||
follow_imports = silent
|
follow_imports = silent
|
||||||
|
|
1
setup.py
1
setup.py
|
@ -40,7 +40,6 @@ REQUIRES = [
|
||||||
"certifi>=2020.12.5",
|
"certifi>=2020.12.5",
|
||||||
"ciso8601==2.1.3",
|
"ciso8601==2.1.3",
|
||||||
"httpx==0.16.1",
|
"httpx==0.16.1",
|
||||||
"importlib-metadata==1.6.0;python_version<'3.8'",
|
|
||||||
"jinja2>=2.11.2",
|
"jinja2>=2.11.2",
|
||||||
"PyJWT==1.7.1",
|
"PyJWT==1.7.1",
|
||||||
# PyJWT has loose dependency. We want the latest one.
|
# PyJWT has loose dependency. We want the latest one.
|
||||||
|
|
|
@ -247,7 +247,7 @@ class MockPlexServer:
|
||||||
"""Mock the playlist lookup method."""
|
"""Mock the playlist lookup method."""
|
||||||
return MockPlexMediaItem(playlist, mediatype="playlist")
|
return MockPlexMediaItem(playlist, mediatype="playlist")
|
||||||
|
|
||||||
@lru_cache()
|
@lru_cache
|
||||||
def playlists(self):
|
def playlists(self):
|
||||||
"""Mock the playlists lookup method with a lazy init."""
|
"""Mock the playlists lookup method with a lazy init."""
|
||||||
return [
|
return [
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
"""The tests for the LG webOS media player platform."""
|
"""The tests for the LG webOS media player platform."""
|
||||||
import sys
|
|
||||||
|
from unittest.mock import patch
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
|
@ -25,12 +26,6 @@ from homeassistant.const import (
|
||||||
)
|
)
|
||||||
from homeassistant.setup import async_setup_component
|
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"
|
NAME = "fake"
|
||||||
ENTITY_ID = f"{media_player.DOMAIN}.{NAME}"
|
ENTITY_ID = f"{media_player.DOMAIN}.{NAME}"
|
||||||
|
|
||||||
|
|
2
tox.ini
2
tox.ini
|
@ -1,5 +1,5 @@
|
||||||
[tox]
|
[tox]
|
||||||
envlist = py37, py38, lint, pylint, typing, cov
|
envlist = py38, py39, lint, pylint, typing, cov
|
||||||
skip_missing_interpreters = True
|
skip_missing_interpreters = True
|
||||||
ignore_basepython_conflict = True
|
ignore_basepython_conflict = True
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue