#1084326 python-aiomodernforms: FTBFS: AttributeError: 'NoneType' object has no attribute 'prepare'

#1084326#5
Date:
2024-10-07 08:38:25 UTC
From:
To:
Dear maintainer:

During a rebuild of all packages in unstable, your package failed to build:
--------------------------------------------------------------------------------
[...]
  debian/rules build
make: pyversions: No such file or directory
py3versions: no X-Python3-Version in control file, using supported versions
dh build --buildsystem=pybuild --with python3
    dh_update_autotools_config -O--buildsystem=pybuild
    dh_autoreconf -O--buildsystem=pybuild
    dh_auto_configure -O--buildsystem=pybuild
    dh_auto_build -O--buildsystem=pybuild
I: pybuild plugin_pyproject:129: Building wheel for python3.12 with "build" module
I: pybuild base:311: python3.12 -m build --skip-dependency-check --no-isolation --wheel --outdir /<<PKGBUILDDIR>>/.pybuild/cpython3_3.12
* Building wheel...
/usr/lib/python3/dist-packages/setuptools/_distutils/dist.py:261: UserWarning: Unknown distribution option: 'test_suite'
   warnings.warn(msg)
/<<PKGBUILDDIR>>/aiomodernforms/__version__.pyrunning bdist_wheel
running build
running build_py
creating build
creating build/lib
creating build/lib/aiomodernforms
copying aiomodernforms/exceptions.py -> build/lib/aiomodernforms
copying aiomodernforms/modernforms.py -> build/lib/aiomodernforms
copying aiomodernforms/__init__.py -> build/lib/aiomodernforms
copying aiomodernforms/const.py -> build/lib/aiomodernforms
copying aiomodernforms/models.py -> build/lib/aiomodernforms
copying aiomodernforms/__version__.py -> build/lib/aiomodernforms
running egg_info
creating aiomodernforms.egg-info
writing aiomodernforms.egg-info/PKG-INFO
writing dependency_links to aiomodernforms.egg-info/dependency_links.txt
writing requirements to aiomodernforms.egg-info/requires.txt
writing top-level names to aiomodernforms.egg-info/top_level.txt
writing manifest file 'aiomodernforms.egg-info/SOURCES.txt'
reading manifest file 'aiomodernforms.egg-info/SOURCES.txt'
reading manifest template 'MANIFEST.in'
warning: no previously-included files matching '*.py[co]' found under directory '*'
adding license file 'LICENSE.md'
writing manifest file 'aiomodernforms.egg-info/SOURCES.txt'
installing to build/bdist.linux-x86_64/wheel
running install
running install_lib
creating build/bdist.linux-x86_64
creating build/bdist.linux-x86_64/wheel
creating build/bdist.linux-x86_64/wheel/aiomodernforms
copying build/lib/aiomodernforms/exceptions.py -> build/bdist.linux-x86_64/wheel/./aiomodernforms
copying build/lib/aiomodernforms/modernforms.py -> build/bdist.linux-x86_64/wheel/./aiomodernforms
copying build/lib/aiomodernforms/__init__.py -> build/bdist.linux-x86_64/wheel/./aiomodernforms
copying build/lib/aiomodernforms/const.py -> build/bdist.linux-x86_64/wheel/./aiomodernforms
copying build/lib/aiomodernforms/models.py -> build/bdist.linux-x86_64/wheel/./aiomodernforms
copying build/lib/aiomodernforms/__version__.py -> build/bdist.linux-x86_64/wheel/./aiomodernforms
running install_egg_info
Copying aiomodernforms.egg-info to build/bdist.linux-x86_64/wheel/./aiomodernforms-0.1.8.egg-info
running install_scripts
creating build/bdist.linux-x86_64/wheel/aiomodernforms-0.1.8.dist-info/WHEEL
creating '/<<PKGBUILDDIR>>/.pybuild/cpython3_3.12/.tmp-0od3vf6_/aiomodernforms-0.1.8-py3-none-any.whl' and adding 'build/bdist.linux-x86_64/wheel' to it
adding 'aiomodernforms/__init__.py'
adding 'aiomodernforms/__version__.py'
adding 'aiomodernforms/const.py'
adding 'aiomodernforms/exceptions.py'
adding 'aiomodernforms/models.py'
adding 'aiomodernforms/modernforms.py'
adding 'aiomodernforms-0.1.8.dist-info/LICENSE.md'
adding 'aiomodernforms-0.1.8.dist-info/METADATA'
adding 'aiomodernforms-0.1.8.dist-info/WHEEL'
adding 'aiomodernforms-0.1.8.dist-info/top_level.txt'
adding 'aiomodernforms-0.1.8.dist-info/RECORD'
removing build/bdist.linux-x86_64/wheel
Successfully built aiomodernforms-0.1.8-py3-none-any.whl
I: pybuild plugin_pyproject:144: Unpacking wheel built for python3.12 with "installer" module
    dh_auto_test -O--buildsystem=pybuild
I: pybuild base:311: cd /<<PKGBUILDDIR>>/.pybuild/cpython3_3.12/build; python3.12 -m pytest -v
/usr/lib/python3/dist-packages/pytest_asyncio/plugin.py:208: PytestDeprecationWarning: The configuration option "asyncio_default_fixture_loop_scope" is unset.
The event loop scope for asynchronous fixtures will default to the fixture caching scope. Future versions of pytest-asyncio will default the loop scope for asynchronous fixtures to function scope. Set the default fixture loop scope explicitly in order to avoid unexpected behavior in the future. Valid fixture loop scopes are: "function", "class", "module", "package", "session"

   warnings.warn(PytestDeprecationWarning(_DEFAULT_FIXTURE_LOOP_SCOPE_UNSET))
============================= test session starts ==============================
platform linux -- Python 3.12.7, pytest-8.3.3, pluggy-1.5.0 -- /usr/bin/python3.12
cachedir: .pytest_cache
rootdir: /<<PKGBUILDDIR>>/.pybuild/cpython3_3.12/build
configfile: pytest.ini
testpaths: tests
plugins: typeguard-4.3.0, asyncio-0.24.0a1, aresponses-3.0.0, cov-5.0.0
asyncio: mode=Mode.STRICT, default_loop_scope=None
collecting ... collected 19 items

tests/test_aiomodernforms.py::test_basic_status PASSED                   [  5%]
tests/test_aiomodernforms.py::test_command PASSED                        [ 10%]
tests/test_aiomodernforms.py::test_light PASSED                          [ 15%]
tests/test_aiomodernforms.py::test_light_sleep_datetime PASSED           [ 21%]
tests/test_aiomodernforms.py::test_light_sleep_int PASSED                [ 26%]
tests/test_aiomodernforms.py::test_light_sleep_clear PASSED              [ 31%]
tests/test_aiomodernforms.py::test_fan PASSED                            [ 36%]
tests/test_aiomodernforms.py::test_fan_sleep_datetime PASSED             [ 42%]
tests/test_aiomodernforms.py::test_fan_sleep_int PASSED                  [ 47%]
tests/test_aiomodernforms.py::test_fan_sleep_clear PASSED                [ 52%]
tests/test_aiomodernforms.py::test_away PASSED                           [ 57%]
tests/test_aiomodernforms.py::test_adaptive_learning PASSED              [ 63%]
tests/test_aiomodernforms.py::test_invalid_setting PASSED                [ 68%]
tests/test_aiomodernforms.py::test_connection_error FAILED               [ 73%]
tests/test_aiomodernforms.py::test_server_error PASSED                   [ 78%]
tests/test_aiomodernforms.py::test_reboot PASSED                         [ 84%]
tests/test_aiomodernforms.py::test_status_not_initialized_response PASSED [ 89%]
tests/test_aiomodernforms.py::test_info_not_initialized_response PASSED  [ 94%]
tests/test_aiomodernforms.py::test_empty_response FAILED                 [100%]

=================================== FAILURES ===================================


tests/test_aiomodernforms.py:502:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
/usr/lib/python3/dist-packages/backoff/_async.py:151: in retry
     ret = await target(*args, **kwargs)
aiomodernforms/modernforms.py:97: in update
     state_data = await self._request()
/usr/lib/python3/dist-packages/backoff/_async.py:151: in retry
     ret = await target(*args, **kwargs)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <aiomodernforms.modernforms.ModernFormsDevice object at 0x7ff98a7d68d0>
commands = {'queryDynamicShadowData': True}

     @backoff.on_exception(
         backoff.expo, ModernFormsConnectionError, max_tries=3, logger=None
     )
     async def _request(self, commands: Optional[dict] = None) -> Any:
         """Handle a request to a Modern Forms Fan device."""
         scheme = "https" if self._tls else "http"
         url = URL.build(
             scheme=scheme,
             host=self._host,
             port=self._port,
             path=self._base_path,
         )

         auth = None
         if self._username and self._password:
             auth = aiohttp.BasicAuth(self._username, self._password)

         headers = {
             "User-Agent": self._user_agent,
             "Accept": "application/json",
         }

         if self._session is None:
             self._session = aiohttp.ClientSession()
             self._close_session = True

         # If updating the state, always request for a state response
         if commands is None:
             commands = {COMMAND_QUERY_STATUS: True}

         try:
             with async_timeout.timeout(self._request_timeout):
                 response = await self._session.request(
                     "POST",
                     url,
                     auth=auth,
                     json=commands,
                     headers=headers,
                     ssl=self._verify_ssl,
                 )
         except asyncio.TimeoutError as exception:
             raise ModernFormsConnectionTimeoutError(
                 "Timeout occurred while connecting to Modern Forms device at"
                 + f" {self._host}"
             ) from exception
         except (aiohttp.ClientError, socket.gaierror) as exception:
             raise ModernFormsConnectionError(
                 "Error occurred while communicating with Modern Forms device at"
                 + f" {self._host}"
             ) from exception

         content_type = response.headers.get("Content-Type", "")
         if (response.status // 100) in [4, 5]:
             contents = await response.read()
             response.close()

             if content_type == "application/json":
                 raise ModernFormsError(
                     response.status, json.loads(contents.decode("utf8"))
                 )
aiomodernforms/modernforms.py:168: ModernFormsError
------------------------------ Captured log call -------------------------------
ERROR    aiohttp.server:web_protocol.py:448 Missing return statement on request handler
Traceback (most recent call last):
   File "/usr/lib/python3/dist-packages/aiohttp/web_protocol.py", line 653, in finish_response
     prepare_meth = resp.prepare
                    ^^^^^^^^^^^^
AttributeError: 'NoneType' object has no attribute 'prepare'

tests/test_aiomodernforms.py:568:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
/usr/lib/python3/dist-packages/backoff/_async.py:151: in retry
     ret = await target(*args, **kwargs)
aiomodernforms/modernforms.py:96: in update
     info_data = await self._request({COMMAND_QUERY_STATIC_DATA: True})
/usr/lib/python3/dist-packages/backoff/_async.py:151: in retry
     ret = await target(*args, **kwargs)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <aiomodernforms.modernforms.ModernFormsDevice object at 0x7ff98a7d9820>
commands = {'queryStaticShadowData': True}

     @backoff.on_exception(
         backoff.expo, ModernFormsConnectionError, max_tries=3, logger=None
     )
     async def _request(self, commands: Optional[dict] = None) -> Any:
         """Handle a request to a Modern Forms Fan device."""
         scheme = "https" if self._tls else "http"
         url = URL.build(
             scheme=scheme,
             host=self._host,
             port=self._port,
             path=self._base_path,
         )

         auth = None
         if self._username and self._password:
             auth = aiohttp.BasicAuth(self._username, self._password)

         headers = {
             "User-Agent": self._user_agent,
             "Accept": "application/json",
         }

         if self._session is None:
             self._session = aiohttp.ClientSession()
             self._close_session = True

         # If updating the state, always request for a state response
         if commands is None:
             commands = {COMMAND_QUERY_STATUS: True}

         try:
             with async_timeout.timeout(self._request_timeout):
                 response = await self._session.request(
                     "POST",
                     url,
                     auth=auth,
                     json=commands,
                     headers=headers,
                     ssl=self._verify_ssl,
                 )
         except asyncio.TimeoutError as exception:
             raise ModernFormsConnectionTimeoutError(
                 "Timeout occurred while connecting to Modern Forms device at"
                 + f" {self._host}"
             ) from exception
         except (aiohttp.ClientError, socket.gaierror) as exception:
             raise ModernFormsConnectionError(
                 "Error occurred while communicating with Modern Forms device at"
                 + f" {self._host}"
             ) from exception

         content_type = response.headers.get("Content-Type", "")
         if (response.status // 100) in [4, 5]:
             contents = await response.read()
             response.close()

             if content_type == "application/json":
                 raise ModernFormsError(
                     response.status, json.loads(contents.decode("utf8"))
                 )
aiomodernforms/modernforms.py:168: ModernFormsError
------------------------------ Captured log call -------------------------------
ERROR    aiohttp.server:web_protocol.py:448 Missing return statement on request handler
Traceback (most recent call last):
   File "/usr/lib/python3/dist-packages/aiohttp/web_protocol.py", line 653, in finish_response
     prepare_meth = resp.prepare
                    ^^^^^^^^^^^^
AttributeError: 'NoneType' object has no attribute 'prepare'
=============================== warnings summary ===============================
tests/test_aiomodernforms.py: 47 warnings
   /<<PKGBUILDDIR>>/.pybuild/cpython3_3.12/build/aiomodernforms/modernforms.py:139: DeprecationWarning: with timeout() is deprecated, use async with timeout() instead
     with async_timeout.timeout(self._request_timeout):

#1084326#10
Date:
2025-11-11 06:45:01 UTC
From:
To:

#1084326#17
Date:
2026-06-16 10:18:41 UTC
From:
To:
We believe that the bug you reported is fixed in the latest version of
python-aiomodernforms, which is due to be installed in the Debian FTP archive.

A summary of the changes between this version and the previous one is
attached.

Thank you for reporting the bug, which will now be closed.  If you
have further comments please address them to 1084326@bugs.debian.org,
and the maintainer will reopen the bug report if appropriate.

Debian distribution maintenance software
pp.
Edward Betts <edward@4angle.com> (supplier of updated python-aiomodernforms package)

(This message was generated automatically at their request; if you
believe that there is a problem with it please contact the archive
administrators by mailing ftpmaster@ftp-master.debian.org)
Format: 1.8
Date: Tue, 16 Jun 2026 10:51:29 +0100
Source: python-aiomodernforms
Architecture: source
Version: 0.1.8-3
Distribution: unstable
Urgency: medium
Maintainer: Home Assistant Team <team+homeassistant@tracker.debian.org>
Changed-By: Edward Betts <edward@4angle.com>
Closes: 1084326
Changes:
 python-aiomodernforms (0.1.8-3) unstable; urgency=medium
 .
   * Team upload.
 .
   [ Edward Betts ]
   * Fix FTBFS with newer aresponses by avoiding exhausted mock routes in
     tests.
   * Add <!nocheck> to test dependencies.
   * Update debian/watch to format version 5.
   * Update Standards-Version.
   * Switch to autopkgtest-pkg-pybuild.
 .
   [ Tianyu Chen ]
   * Replace async-timeout with asyncio.timeout. (Closes: #1084326)
   * Add debian/salsa-ci.yml.
Checksums-Sha1:
 2b610ec633b968163a525e72c4f2ec73a43583d3 2484 python-aiomodernforms_0.1.8-3.dsc
 2b33496ab089f9f5ac438eda50dd9cb0c63f2d3d 3852 python-aiomodernforms_0.1.8-3.debian.tar.xz
 7033a8e8bba73168623bb877e8f3900ced5c6c11 7268 python-aiomodernforms_0.1.8-3_source.buildinfo
Checksums-Sha256:
 d74c145313b05aa316f05b123cd08452846388e54622b41a6b3ee84af70e5aac 2484 python-aiomodernforms_0.1.8-3.dsc
 778c6cc48219952ab13e4f09d87061964770e0c965cf1e1be0f7dbd05a1ce0b1 3852 python-aiomodernforms_0.1.8-3.debian.tar.xz
 71b09da0f033344c44cf3159e73a9b6ee0778d7ee555a992625020644fdca53b 7268 python-aiomodernforms_0.1.8-3_source.buildinfo
Files:
 199a96a623afad68a57610cbb325e320 2484 python optional python-aiomodernforms_0.1.8-3.dsc
 9cdd75b593e89d4f85b33ef95091b3bf 3852 python optional python-aiomodernforms_0.1.8-3.debian.tar.xz
 6c57eed64587e802a3ad26d589423a6c 7268 python optional python-aiomodernforms_0.1.8-3_source.buildinfo
-----BEGIN PGP SIGNATURE-----

iQIzBAEBCgAdFiEE+4rPp4xyYInDitAmlgWhCYxjuSoFAmoxHxcACgkQlgWhCYxj
uSrnlA//aSEYjgCzCQEeinn9m278ehNhb2hZzir0nqLJHx0TJ2uH0URiHyTSqTVt
eQc79p/vvxOpR4FLAFUflyPPnY3hDvB8gSTtgMMTEUTUl/th1oXNtEDvcu/ykfOI
dgecAG86hesDMu4DBQTZvWhnmYGX6uqtsz1Hrl2+q1+aVlq0PcBT3q42iK/EpvZ2
AXKNq6cQ4KgwKL2BeUitYQAyBbobljPonVY9jsWAM8kZdV/nGn/EOlr7U+lffK1e
k57dHiISvTxP4lmV0VJ0ch24YNOXCT5NN2WAEsDh3u1SSWTUMReQzzlFxmQXnlEn
08w0V1CLAz2OZVkvDE9B/ROYJ8UkRULTDqFaAu2I/xHasclxpxhRSWaVApjoAhJV
mNu1CuMGvwlXGDa+JzCGT5BTmkLtuV97h2kVPGfXjCMHt7HYzV6jzKZr9FGcxg+i
d0ADqf96SrbIRydqQWJQNnmAKBM5GYDo54D6DsK2QMEBwAXFqbLXuqQOUAe4WKFg
jNcKfUjDQwfXt8mdOhbW1O8S24nEN+IYn5Q8QvXJuS4UWr9E+2h5O4g7QINhRyrL
O3HTu9GtfKeKmGX7y15VFeF3v1FEIkttCSTMyHS9m15900xG6JKe+929jYPAq44o
+Ri/MAj3oyWgpuhmSFOXjek8eHbZWa3waZuVP68bSDXI2qfFYqs=
=S+iw
-----END PGP SIGNATURE-----