Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Using synchronously seems to require async? #123

Closed
wilg opened this issue Aug 13, 2022 · 8 comments · Fixed by #125
Closed

Using synchronously seems to require async? #123

wilg opened this issue Aug 13, 2022 · 8 comments · Fixed by #125
Assignees
Labels
bug Something isn't working

Comments

@wilg
Copy link

wilg commented Aug 13, 2022

I'm trying to do some really basic stuff but I can't get it to work:

from homeassistant_api import Client

import pprint
import os

def fetch_homeassistant_data():
  url = os.getenv('HOMEASSISTANT_URL')
  token = os.getenv("HOMEASSISTANT_TOKEN")

  assert token is not None

  with Client(url, token) as client:
    sun = client.get_entity(entity_id="sun.sun")
    state = sun.get_state()

    pprint(state)

throws this error:

  File "/Users/wil/Code/solar-frame/solarframe/ha_data.py", line 12, in fetch_homeassistant_data
    with Client(url, token) as client:
  File "/Users/wil/.local/share/virtualenvs/solar-frame-gF3PVx5E/lib/python3.9/site-packages/homeassistant_api/client.py", line 25, in __init__
    super().__init__(*args, **kwargs)
  File "/Users/wil/.local/share/virtualenvs/solar-frame-gF3PVx5E/lib/python3.9/site-packages/homeassistant_api/rawclient.py", line 58, in __init__
    super().__init__(*args, **kwargs)
  File "/Users/wil/.local/share/virtualenvs/solar-frame-gF3PVx5E/lib/python3.9/site-packages/homeassistant_api/rawasyncclient.py", line 63, in __init__
    self.async_cache_session = aiohttp_client_cache.CachedSession(
  File "/Users/wil/.local/share/virtualenvs/solar-frame-gF3PVx5E/lib/python3.9/site-packages/forge/_revision.py", line 328, in inner
    return callable(*mapped.args, **mapped.kwargs)
  File "/Users/wil/.local/share/virtualenvs/solar-frame-gF3PVx5E/lib/python3.9/site-packages/aiohttp_client_cache/session.py", line 37, in __init__
    super().__init__(**session_kwargs)
  File "/Users/wil/.local/share/virtualenvs/solar-frame-gF3PVx5E/lib/python3.9/site-packages/aiohttp/client.py", line 227, in __init__
    loop = get_running_loop(loop)
  File "/Users/wil/.local/share/virtualenvs/solar-frame-gF3PVx5E/lib/python3.9/site-packages/aiohttp/helpers.py", line 288, in get_running_loop
    loop = asyncio.get_event_loop()
  File "/opt/homebrew/Cellar/python@3.9/3.9.12/Frameworks/Python.framework/Versions/3.9/lib/python3.9/asyncio/events.py", line 642, in get_event_loop
    raise RuntimeError('There is no current event loop in thread %r.'
RuntimeError: There is no current event loop in thread 'Thread-1'.
----------------------------------------
Exception ignored in: <function ClientSession.__del__ at 0x1067ad430>
Traceback (most recent call last):
  File "/Users/wil/.local/share/virtualenvs/solar-frame-gF3PVx5E/lib/python3.9/site-packages/aiohttp/client.py", line 336, in __del__
    if not self.closed:
  File "/Users/wil/.local/share/virtualenvs/solar-frame-gF3PVx5E/lib/python3.9/site-packages/aiohttp/client.py", line 986, in closed
    return self._connector is None or self._connector.closed
AttributeError: 'CachedSession' object has no attribute '_connector'
@wilg wilg added the bug Something isn't working label Aug 13, 2022
@GrandMoff100
Copy link
Owner

GrandMoff100 commented Aug 13, 2022

Yeah I know why this is happening. In the init method of Client if you pass cached_session=... it will initialize its synchronous parent, and if you pass async_cached_session=... it initializes as an asynchronous parent, if neither are passed it initializes as both haha. The mysterious super function at work. The current fix it just pass cached_session=False which explicitly disables caching while also telling it to use its sync parent, or cached_session=None telling it to use a default cache session. In the future I need to implement a function the checks whether the context calling Client is sync or async and use that as the condition for which parent to initialize, similar to how Service.__call__ works. Thoughts?

@wilg
Copy link
Author

wilg commented Aug 13, 2022

I'm a Python newbie, so I don't have any good suggestion for you on what to do. Maybe just explicitly initialize sync vs async? I'll try the workaround. I actually tried something similar after poking around the code but I passed None instead of False.

@wilg
Copy link
Author

wilg commented Aug 13, 2022

Unfortunately that workaround doesn't work. The parameter is spelled cache_session, but neither Client(url, token, cache_session=None) nor Client(url, token, cache_session=False) works, throwing the same error as I posted originally.

@wilg
Copy link
Author

wilg commented Aug 13, 2022

I don't really understand how that's happening, since when passing that argument it appears to initialize RawClient not RawAsyncClient but it somehow initializes the async client anyway:

  File "/Users/wil/Code/solar-frame/solarframe/ha_data.py", line 12, in fetch_homeassistant_data
    with Client(url, token, cache_session=False) as client:
  File "/Users/wil/.local/share/virtualenvs/solar-frame-gF3PVx5E/lib/python3.9/site-packages/homeassistant_api/client.py", line 21, in __init__
    RawClient.__init__(self, *args, **kwargs)
  File "/Users/wil/.local/share/virtualenvs/solar-frame-gF3PVx5E/lib/python3.9/site-packages/homeassistant_api/rawclient.py", line 58, in __init__
    super().__init__(*args, **kwargs)
  File "/Users/wil/.local/share/virtualenvs/solar-frame-gF3PVx5E/lib/python3.9/site-packages/homeassistant_api/rawasyncclient.py", line 63, in __init__
    self.async_cache_session = aiohttp_client_cache.CachedSession(
  File "/Users/wil/.local/share/virtualenvs/solar-frame-gF3PVx5E/lib/python3.9/site-packages/forge/_revision.py", line 328, in inner
    return callable(*mapped.args, **mapped.kwargs)

@GrandMoff100
Copy link
Owner

GrandMoff100 commented Aug 13, 2022

Sorry, yes the parameters are async_cache_session and cache_session, not cached_session, my bad.

In homeassistant_api/client.py

def __init__(self, *args: Any, **kwargs: Any) -> None:
        if "cache_session" in kwargs:
            RawClient.__init__(self, *args, **kwargs)
        elif "async_cache_session" in kwargs:
            RawAsyncClient.__init__(self, *args, **kwargs)
        else:
            super().__init__(*args, **kwargs)

When cache_session=<something> is passed it shows up in the dictionary of keyword arguments which is **kwargs. So what this code does is choose an init method based on what parameters are passed. Another workaround is probably to use RawClient directly from homeassistant_api.rawclient instead of Client.

@wilg
Copy link
Author

wilg commented Aug 14, 2022

That's what I thought was going on, but I still can't get it to work even with Client(url, token, cache_session=False, async_cache_session=False).

@wilg
Copy link
Author

wilg commented Aug 14, 2022

And I can't seem to import RawClient:

from homeassistant_api import RawClient
ImportError: cannot import name 'RawClient' from 'homeassistant_api'

and

from homeassistant_api.rawclient import RawClient
Traceback (most recent call last):
  File "/opt/homebrew/Cellar/python@3.9/3.9.12/Frameworks/Python.framework/Versions/3.9/lib/python3.9/socketserver.py", line 683, in process_request_thread
    self.finish_request(request, client_address)
  File "/opt/homebrew/Cellar/python@3.9/3.9.12/Frameworks/Python.framework/Versions/3.9/lib/python3.9/socketserver.py", line 360, in finish_request
    self.RequestHandlerClass(request, client_address, self)
  File "/opt/homebrew/Cellar/python@3.9/3.9.12/Frameworks/Python.framework/Versions/3.9/lib/python3.9/socketserver.py", line 747, in __init__
    self.handle()
  File "/opt/homebrew/Cellar/python@3.9/3.9.12/Frameworks/Python.framework/Versions/3.9/lib/python3.9/http/server.py", line 425, in handle
    self.handle_one_request()
  File "/opt/homebrew/Cellar/python@3.9/3.9.12/Frameworks/Python.framework/Versions/3.9/lib/python3.9/http/server.py", line 413, in handle_one_request
    method()
  File "/Users/wil/Code/solar-frame/app.py", line 25, in do_GET
    self.do_sample()
  File "/Users/wil/Code/solar-frame/app.py", line 35, in do_sample
    img = self.powerwall_image(config)
  File "/Users/wil/Code/solar-frame/app.py", line 73, in powerwall_image
    fetch_homeassistant_data()
  File "/Users/wil/Code/solar-frame/solarframe/ha_data.py", line 15, in fetch_homeassistant_data
    pprint(state)
TypeError: 'module' object is not callable

@GrandMoff100
Copy link
Owner

I don't think thats a problem with homeassistant_api because i can execute it just fine

 $ python -m venv .venv
 $ . .venv/bin/activate
(.venv) $ pip install homeassistant_api
Collecting homeassistant_api
  Using cached HomeAssistant_API-4.0.0.post1-py3-none-any.whl (34 kB)
Collecting requests-cache<0.10.0,>=0.9.2
  Using cached requests_cache-0.9.5-py3-none-any.whl (47 kB)
Collecting requests==2.27.1
  Using cached requests-2.27.1-py2.py3-none-any.whl (63 kB)
Collecting pydantic<=1.9.0
  Using cached pydantic-1.9.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (12.3 MB)
Collecting aiohttp<4.0.0,>=3.8.1
  Using cached aiohttp-3.8.1-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl (1.2 MB)
Collecting aiohttp-client-cache<0.7.0,>=0.6.1
  Using cached aiohttp_client_cache-0.6.1-py3-none-any.whl (31 kB)
Collecting simplejson<4.0.0,>=3.17.6
  Using cached simplejson-3.17.6-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl (137 kB)
Collecting charset-normalizer~=2.0.0
  Using cached charset_normalizer-2.0.12-py3-none-any.whl (39 kB)
Collecting certifi>=2017.4.17
  Using cached certifi-2022.6.15-py3-none-any.whl (160 kB)
Collecting idna<4,>=2.5
  Using cached idna-3.3-py3-none-any.whl (61 kB)
Collecting urllib3<1.27,>=1.21.1
  Using cached urllib3-1.26.11-py2.py3-none-any.whl (139 kB)
Collecting async-timeout<5.0,>=4.0.0a3
  Using cached async_timeout-4.0.2-py3-none-any.whl (5.8 kB)
Collecting frozenlist>=1.1.1
  Using cached frozenlist-1.3.1-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl (149 kB)
Collecting aiosignal>=1.1.2
  Using cached aiosignal-1.2.0-py3-none-any.whl (8.2 kB)
Collecting attrs>=17.3.0
  Using cached attrs-22.1.0-py2.py3-none-any.whl (58 kB)
Collecting multidict<7.0,>=4.5
  Using cached multidict-6.0.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (114 kB)
Collecting yarl<2.0,>=1.0
  Using cached yarl-1.8.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (263 kB)
Collecting python-forge<19.0,>=18.6
  Using cached python_forge-18.6.0-py35-none-any.whl (31 kB)
Collecting attrs>=17.3.0
  Using cached attrs-21.4.0-py2.py3-none-any.whl (60 kB)
Collecting url-normalize<2.0,>=1.4
  Using cached url_normalize-1.4.3-py2.py3-none-any.whl (6.8 kB)
Collecting itsdangerous
  Using cached itsdangerous-2.1.2-py3-none-any.whl (15 kB)
Collecting typing-extensions>=3.7.4.3
  Using cached typing_extensions-4.3.0-py3-none-any.whl (25 kB)
Collecting exceptiongroup>=1.0.0-rc.3
  Using cached exceptiongroup-1.0.0rc8-py3-none-any.whl (11 kB)
Collecting appdirs<2.0.0,>=1.4.4
  Using cached appdirs-1.4.4-py2.py3-none-any.whl (9.6 kB)
Collecting cattrs<=22.2,>=1.8
  Downloading cattrs-22.1.0-py3-none-any.whl (33 kB)
Collecting cchardet
  Downloading cchardet-2.1.7.tar.gz (653 kB)
     ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 653.6/653.6 KB 3.3 MB/s eta 0:00:00
  Preparing metadata (setup.py) ... done
Collecting Brotli
  Downloading Brotli-1.0.9-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl (2.7 MB)
     ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 2.7/2.7 MB 1.6 MB/s eta 0:00:00
Collecting aiodns
  Downloading aiodns-3.0.0-py3-none-any.whl (5.0 kB)
Collecting six
  Using cached six-1.16.0-py2.py3-none-any.whl (11 kB)
Collecting pycares>=4.0.0
  Downloading pycares-4.2.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (289 kB)
     ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 289.4/289.4 KB 806.5 kB/s eta 0:00:00
Collecting cffi>=1.5.0
  Using cached cffi-1.15.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (441 kB)
Collecting pycparser
  Using cached pycparser-2.21-py2.py3-none-any.whl (118 kB)
Using legacy 'setup.py install' for cchardet, since package 'wheel' is not installed.
Installing collected packages: python-forge, cchardet, Brotli, appdirs, urllib3, typing-extensions, six, simplejson, pycparser, multidict, itsdangerous, idna, frozenlist, exceptiongroup, charset-normalizer, certifi, attrs, async-timeout, yarl, url-normalize, requests, pydantic, cffi, cattrs, aiosignal, requests-cache, pycares, aiohttp, aiodns, aiohttp-client-cache, homeassistant_api
  Running setup.py install for cchardet ... done
Successfully installed Brotli-1.0.9 aiodns-3.0.0 aiohttp-3.8.1 aiohttp-client-cache-0.6.1 aiosignal-1.2.0 appdirs-1.4.4 async-timeout-4.0.2 attrs-21.4.0 cattrs-22.1.0 cchardet-2.1.7 certifi-2022.6.15 cffi-1.15.1 charset-normalizer-2.0.12 exceptiongroup-1.0.0rc8 frozenlist-1.3.1 homeassistant_api-4.0.0.post1 idna-3.3 itsdangerous-2.1.2 multidict-6.0.2 pycares-4.2.2 pycparser-2.21 pydantic-1.9.0 python-forge-18.6.0 requests-2.27.1 requests-cache-0.9.5 simplejson-3.17.6 six-1.16.0 typing-extensions-4.3.0 url-normalize-1.4.3 urllib3-1.26.11 yarl-1.8.1
(.venv) $ pip --version
pip 22.0.2 from /workspace/testing/.venv/lib/python3.10/site-packages/pip (python 3.10)
(.venv) $ python
Python 3.10.4 (main, Jun 29 2022, 12:14:53) [GCC 11.2.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> from homeassistant_api.rawclient import RawClient
>>> # Notice no error
>>>

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
2 participants