Skip to content

Commit

Permalink
Merge pull request #196 from dvd-dev/blocking_call3
Browse files Browse the repository at this point in the history
Amélioration pour éviter les blocking calls au disque
  • Loading branch information
ic-dev21 authored Jun 12, 2024
2 parents d41d9f6 + b3c365f commit 4325952
Show file tree
Hide file tree
Showing 6 changed files with 30 additions and 23 deletions.
1 change: 1 addition & 0 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ repos:
files: ^pyhilo/.+\.py$
additional_dependencies:
- types-python-dateutil==2.8.0
- types-aiofiles==23.2.0

- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v2.4.0
Expand Down
25 changes: 13 additions & 12 deletions pyhilo/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
from pyhilo.device import DeviceAttribute, HiloDevice, get_device_attributes
from pyhilo.exceptions import InvalidCredentialsError, RequestError
from pyhilo.util.state import (
StateDict,
WebsocketDict,
WebsocketTransportsDict,
get_state,
Expand Down Expand Up @@ -75,7 +76,7 @@ def __init__(
self._backoff_refresh_lock_ws = asyncio.Lock()
self._request_retries = request_retries
self._state_yaml: str = DEFAULT_STATE_FILE
self.state = get_state(self._state_yaml)
self.state: StateDict = {}
self.async_request = self._wrap_request_method(self._request_retries)
self.device_attributes = get_device_attributes()
self.session: ClientSession = session
Expand Down Expand Up @@ -152,14 +153,14 @@ def dev_atts(
else attribute,
)

def _get_fid_state(self) -> bool:
async def _get_fid_state(self) -> bool:
"""Looks up the cached state to define the firebase attributes
on the API instances.
:return: Whether or not we have cached firebase state
:rtype: bool
"""
self.state = get_state(self._state_yaml)
self.state = await get_state(self._state_yaml)
fb_state = self.state.get("firebase", {})
if fb_fid := fb_state.get("fid"):
self._fb_fid = fb_fid
Expand All @@ -171,14 +172,14 @@ def _get_fid_state(self) -> bool:
return True
return False

def _get_android_state(self) -> bool:
async def _get_android_state(self) -> bool:
"""Looks up the cached state to define the android device token
on the API instances.
:return: Whether or not we have cached android state
:rtype: bool
"""
self.state = get_state(self._state_yaml)
self.state = await get_state(self._state_yaml)
android_state = self.state.get("android", {})
if token := android_state.get("token"):
self._device_token = token
Expand All @@ -187,18 +188,18 @@ def _get_android_state(self) -> bool:

async def _get_device_token(self) -> None:
"""Retrieves the android token if it's not cached."""
if not self._get_android_state():
if not await self._get_android_state():
await self.android_register()

async def _get_fid(self) -> None:
"""Retrieves the firebase state if it's not cached."""
if not self._get_fid_state():
if not await self._get_fid_state():
self._fb_id = "".join(
random.SystemRandom().choice(string.ascii_letters + string.digits)
for _ in range(FB_ID_LEN)
)
await self.fb_install(self._fb_id)
self._get_fid_state()
await self._get_fid_state()

async def _async_request(
self, method: str, endpoint: str, host: str = API_HOSTNAME, **kwargs: Any
Expand Down Expand Up @@ -366,7 +367,7 @@ async def post_devicehub_negociate(self) -> tuple[str, str]:
resp = await self.async_request("post", url)
ws_url = resp.get("url")
ws_token = resp.get("accessToken")
set_state(
await set_state(
self._state_yaml,
"websocket",
{
Expand Down Expand Up @@ -397,7 +398,7 @@ async def get_websocket_params(self) -> None:
"available_transports": transport_dict,
"full_ws_url": self.full_ws_url,
}
set_state(self._state_yaml, "websocket", websocket_dict)
await set_state(self._state_yaml, "websocket", websocket_dict)

async def fb_install(self, fb_id: str) -> None:
LOG.debug("Posting firebase install")
Expand All @@ -422,7 +423,7 @@ async def fb_install(self, fb_id: str) -> None:
raise RequestError(err) from err
LOG.debug(f"FB Install data: {resp}")
auth_token = resp.get("authToken", {})
set_state(
await set_state(
self._state_yaml,
"firebase",
{
Expand Down Expand Up @@ -463,7 +464,7 @@ async def android_register(self) -> None:
LOG.error(f"Android registration error: {msg}")
raise RequestError
token = msg.split("=")[-1]
set_state(
await set_state(
self._state_yaml,
"android",
{
Expand Down
2 changes: 1 addition & 1 deletion pyhilo/const.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
LOG: Final = logging.getLogger(__package__)
DEFAULT_STATE_FILE: Final = "hilo_state.yaml"
REQUEST_RETRY: Final = 9
PYHILO_VERSION: Final = "2024.04.01"
PYHILO_VERSION: Final = "2024.06.01"
# TODO: Find a way to keep previous line in sync with pyproject.toml automatically

CONTENT_TYPE_FORM: Final = "application/x-www-form-urlencoded"
Expand Down
17 changes: 10 additions & 7 deletions pyhilo/util/state.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
from os.path import isfile
from typing import Any, Optional, Type, TypedDict, TypeVar, Union

import aiofiles
import ruyaml as yaml

from pyhilo.const import LOG
Expand Down Expand Up @@ -71,21 +72,22 @@ def __get_defaults__(cls: Type[T]) -> dict[str, Any]:
return new_dict # type: ignore


def get_state(state_yaml: str) -> StateDict:
async def get_state(state_yaml: str) -> StateDict:
"""Read in state yaml.
:param state_yaml: filename where to read the state
:type state_yaml: ``str``
:rtype: ``StateDict``
"""
if not isfile(state_yaml):
return __get_defaults__(StateDict) # type: ignore
with open(state_yaml) as yaml_file:
async with aiofiles.open(state_yaml, mode="r") as yaml_file:
LOG.debug("Loading state from yaml")
state_yaml_payload: StateDict = yaml.load(yaml_file, Loader=yaml.Loader)
content = await yaml_file.read()
state_yaml_payload: StateDict = yaml.safe_load(content)
return state_yaml_payload


def set_state(
async def set_state(
state_yaml: str,
key: str,
state: Union[
Expand All @@ -101,9 +103,10 @@ def set_state(
:type state: ``StateDict``
:rtype: ``StateDict``
"""
current_state = get_state(state_yaml) or {}
current_state = await get_state(state_yaml) or {}
merged_state: dict[str, Any] = {key: {**current_state.get(key, {}), **state}} # type: ignore
new_state: dict[str, Any] = {**current_state, **merged_state}
with open(state_yaml, "w") as yaml_file:
async with aiofiles.open(state_yaml, mode="w") as yaml_file:
LOG.debug("Saving state to yaml file")
yaml.dump(new_state, yaml_file, Dumper=yaml.RoundTripDumper)
content = yaml.dump(new_state)
await yaml_file.write(content)
7 changes: 4 additions & 3 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ disallow_untyped_defs = true
follow_imports = "silent"
ignore_missing_imports = true
no_implicit_optional = true
python_version = "3.9"
python_version = "3.11"
show_error_codes = true
strict_equality = true
warn_incomplete_stub = true
Expand All @@ -40,7 +40,7 @@ exclude = ".venv/.*"

[tool.poetry]
name = "python-hilo"
version = "2024.4.1"
version = "2024.6.1"
description = "A Python3, async interface to the Hilo API"
readme = "README.md"
authors = ["David Vallee Delisle <[email protected]>"]
Expand All @@ -65,6 +65,7 @@ classifiers = [

[tool.poetry.dependencies]
aiohttp = ">=3.8.0"
aiofiles = ">=23.2.1"
aiosignal = ">=1.2.0"
async-timeout = ">=4.0.0"
attrs = ">=21.2.0"
Expand All @@ -73,7 +74,7 @@ python-dateutil = ">=2.8.2"
ruyaml = ">=0.91.0"
python = "^3.9.0"
voluptuous = ">=0.13.1"
websockets = ">=8.1,<12.0"
websockets = ">=8.1,<13.0"

[tool.poetry.dev-dependencies]
Sphinx = "^7.1.2"
Expand Down
1 change: 1 addition & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
aiofiles >=23.2.1
aiohttp>=3.8.0
aiosignal>=1.1.0
async-timeout>=4.0.0
Expand Down

0 comments on commit 4325952

Please sign in to comment.