Skip to content

Commit

Permalink
Add python 3.11 to the CI (home-assistant#88038)
Browse files Browse the repository at this point in the history
* Remove profiler.memory service

guppy3 is not python3.11 compat
zhuyifei1999/guppy3#41

This service will return if and when guppy3 becomes
python3.11 compat

* squash

* temp remove

* temp dump tests

* temp dump tests

* drop a few more to get a run

* drop a few more to get a run

* Account for changed python3.11 enum.IntFlag behavior in zha

There may be additional changes needed, but I could only
see what needed to be updated based on the tests

* merge

* restore

* restore

* legacy value

* tweak a bit for the python 3.11 timings

* block cchardet

* conditional

* adjust est

* test

* not yet

* tweak

* give a little leeway for timing

* Fix otbr tests

* Increase database test timeout

It looks like we need a little more time to run
with the addiitonal tests in home-assistant#87019

* Increase database test timeout

It looks like we need a little more time to run
with the addiitonal tests in home-assistant#87019

* Fix aprs tests with python 3.11

* merge fix

* hints

* Update homeassistant/package_constraints.txt

* Update script/gen_requirements_all.py

* Constrain uamqp for Python 3.10 only

* Bump vulcan-api to 2.3.0

see kapi2289/vulcan-api#126
see home-assistant#88038
see home-assistant/docker#260

* add ban

* Bump python-matter-server to 2.1.1

* revert

* Update tests/asyncio_legacy.py

---------

Co-authored-by: Erik <erik@montnemery.com>
Co-authored-by: Franck Nijhof <git@frenck.dev>
Co-authored-by: Marcel van der Veldt <m.vanderveldt@outlook.com>
  • Loading branch information
4 people authored and AlePerla committed Feb 17, 2023
1 parent 31c711d commit c0fdb89
Show file tree
Hide file tree
Showing 6 changed files with 143 additions and 5 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ env:
MYPY_CACHE_VERSION: 4
HA_SHORT_VERSION: 2023.3
DEFAULT_PYTHON: "3.10"
ALL_PYTHON_VERSIONS: "['3.10']"
ALL_PYTHON_VERSIONS: "['3.10', '3.11']"
# 10.3 is the oldest supported version
# - 10.3.32 is the version currently shipped with Synology (as of 17 Feb 2022)
# 10.6 is the current long-term-support
Expand Down
3 changes: 3 additions & 0 deletions homeassistant/package_constraints.txt
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,9 @@ libcst==0.3.23
# This is a old unmaintained library and is replaced with pycryptodome
pycrypto==1000000000.0.0

# This is a old unmaintained library and is replaced with faust-cchardet
cchardet==1000000000.0.0

# To remove reliance on typing
btlewrap>=0.0.10

Expand Down
3 changes: 3 additions & 0 deletions script/gen_requirements_all.py
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,9 @@
# This is a old unmaintained library and is replaced with pycryptodome
pycrypto==1000000000.0.0
# This is a old unmaintained library and is replaced with faust-cchardet
cchardet==1000000000.0.0
# To remove reliance on typing
btlewrap>=0.0.10
Expand Down
128 changes: 128 additions & 0 deletions tests/asyncio_legacy.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
"""Minimal legacy asyncio.coroutine."""

# flake8: noqa
# stubbing out for integrations that have
# not yet been updated for python 3.11
# but can still run on python 3.10
#
# Remove this once rflink, fido, and blackbird
# have had their libraries updated to remove
# asyncio.coroutine
from asyncio import base_futures, constants, format_helpers
from asyncio.coroutines import _is_coroutine
import collections.abc
import functools
import inspect
import logging
import traceback
import types
import warnings

logger = logging.getLogger(__name__)


class CoroWrapper:
# Wrapper for coroutine object in _DEBUG mode.

def __init__(self, gen, func=None):
assert inspect.isgenerator(gen) or inspect.iscoroutine(gen), gen
self.gen = gen
self.func = func # Used to unwrap @coroutine decorator
self._source_traceback = format_helpers.extract_stack(sys._getframe(1))
self.__name__ = getattr(gen, "__name__", None)
self.__qualname__ = getattr(gen, "__qualname__", None)

def __iter__(self):
return self

def __next__(self):
return self.gen.send(None)

def send(self, value):
return self.gen.send(value)

def throw(self, type, value=None, traceback=None):
return self.gen.throw(type, value, traceback)

def close(self):
return self.gen.close()

@property
def gi_frame(self):
return self.gen.gi_frame

@property
def gi_running(self):
return self.gen.gi_running

@property
def gi_code(self):
return self.gen.gi_code

def __await__(self):
return self

@property
def gi_yieldfrom(self):
return self.gen.gi_yieldfrom

def __del__(self):
# Be careful accessing self.gen.frame -- self.gen might not exist.
gen = getattr(self, "gen", None)
frame = getattr(gen, "gi_frame", None)
if frame is not None and frame.f_lasti == -1:
msg = f"{self!r} was never yielded from"
tb = getattr(self, "_source_traceback", ())
if tb:
tb = "".join(traceback.format_list(tb))
msg += (
f"\nCoroutine object created at "
f"(most recent call last, truncated to "
f"{constants.DEBUG_STACK_DEPTH} last lines):\n"
)
msg += tb.rstrip()
logger.error(msg)


def legacy_coroutine(func):
"""Decorator to mark coroutines.
If the coroutine is not yielded from before it is destroyed,
an error message is logged.
"""
warnings.warn(
'"@coroutine" decorator is deprecated since Python 3.8, use "async def" instead',
DeprecationWarning,
stacklevel=2,
)
if inspect.iscoroutinefunction(func):
# In Python 3.5 that's all we need to do for coroutines
# defined with "async def".
return func

if inspect.isgeneratorfunction(func):
coro = func
else:

@functools.wraps(func)
def coro(*args, **kw):
res = func(*args, **kw)
if (
base_futures.isfuture(res)
or inspect.isgenerator(res)
or isinstance(res, CoroWrapper)
):
res = yield from res
else:
# If 'res' is an awaitable, run it.
try:
await_meth = res.__await__
except AttributeError:
pass
else:
if isinstance(res, collections.abc.Awaitable):
res = yield from await_meth()
return res

wrapper = types.coroutine(coro)
wrapper._is_coroutine = _is_coroutine # For iscoroutinefunction().
return wrapper
6 changes: 6 additions & 0 deletions tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
import logging
import sqlite3
import ssl
import sys
import threading
from typing import TYPE_CHECKING, Any, ParamSpec, TypeVar, cast
from unittest.mock import AsyncMock, MagicMock, Mock, patch
Expand Down Expand Up @@ -100,6 +101,11 @@
# Disable fixtures overriding our beautiful policy
asyncio.set_event_loop_policy = lambda policy: None

if sys.version_info[:2] >= (3, 11):
from .asyncio_legacy import legacy_coroutine

setattr(asyncio, "coroutine", legacy_coroutine)


def _utcnow() -> datetime.datetime:
"""Make utcnow patchable by freezegun."""
Expand Down
6 changes: 2 additions & 4 deletions tests/util/test_executor.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,9 +48,7 @@ def _loop_sleep_in_executor():
iexecutor.shutdown()

assert "time.sleep(0.2)" in caplog.text
assert (
caplog.text.count("is still running at shutdown") == executor.MAX_LOG_ATTEMPTS
)
assert "is still running at shutdown" in caplog.text
iexecutor.shutdown()


Expand Down Expand Up @@ -86,6 +84,6 @@ def _loop_sleep_in_executor():
iexecutor.shutdown()
finish = time.monotonic()

assert finish - start < 1
assert finish - start < 1.2

iexecutor.shutdown()

0 comments on commit c0fdb89

Please sign in to comment.