python-hilo 2026.9.1__tar.gz → 2026.10.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {python_hilo-2026.9.1 → python_hilo-2026.10.1}/.github/workflows/release-drafter.yml +1 -1
- {python_hilo-2026.9.1 → python_hilo-2026.10.1}/.github/workflows/tests.yaml +2 -2
- {python_hilo-2026.9.1 → python_hilo-2026.10.1}/PKG-INFO +1 -1
- {python_hilo-2026.9.1 → python_hilo-2026.10.1}/pyhilo/api.py +5 -1
- {python_hilo-2026.9.1 → python_hilo-2026.10.1}/pyhilo/const.py +1 -1
- {python_hilo-2026.9.1 → python_hilo-2026.10.1}/pyhilo/util/state.py +14 -8
- {python_hilo-2026.9.1 → python_hilo-2026.10.1}/pyproject.toml +1 -1
- python_hilo-2026.10.1/uv.lock +1643 -0
- python_hilo-2026.9.1/uv.lock +0 -1434
- {python_hilo-2026.9.1 → python_hilo-2026.10.1}/.bandit.yaml +0 -0
- {python_hilo-2026.9.1 → python_hilo-2026.10.1}/.devcontainer/devcontainer-lock.json +0 -0
- {python_hilo-2026.9.1 → python_hilo-2026.10.1}/.devcontainer/devcontainer.json +0 -0
- {python_hilo-2026.9.1 → python_hilo-2026.10.1}/.editorconfig +0 -0
- {python_hilo-2026.9.1 → python_hilo-2026.10.1}/.gitattributes +0 -0
- {python_hilo-2026.9.1 → python_hilo-2026.10.1}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
- {python_hilo-2026.9.1 → python_hilo-2026.10.1}/.github/ISSUE_TEMPLATE/issue.md +0 -0
- {python_hilo-2026.9.1 → python_hilo-2026.10.1}/.github/dependabot.yml +0 -0
- {python_hilo-2026.9.1 → python_hilo-2026.10.1}/.github/labels.yml +0 -0
- {python_hilo-2026.9.1 → python_hilo-2026.10.1}/.github/release-drafter.yml +0 -0
- {python_hilo-2026.9.1 → python_hilo-2026.10.1}/.github/workflows/labeler.yml +0 -0
- {python_hilo-2026.9.1 → python_hilo-2026.10.1}/.gitignore +0 -0
- {python_hilo-2026.9.1 → python_hilo-2026.10.1}/.pre-commit-config.yaml +0 -0
- {python_hilo-2026.9.1 → python_hilo-2026.10.1}/LICENSE +0 -0
- {python_hilo-2026.9.1 → python_hilo-2026.10.1}/README.md +0 -0
- {python_hilo-2026.9.1 → python_hilo-2026.10.1}/doc/Challenge(Event) JSON/ChallengeAdded.json +0 -0
- {python_hilo-2026.9.1 → python_hilo-2026.10.1}/doc/Challenge(Event) JSON/EventAdded.json +0 -0
- {python_hilo-2026.9.1 → python_hilo-2026.10.1}/doc/Challenge(Event) JSON/EventCHConsumptionUpdatedValuesReceived(en cours de d/303/251fi).json" +0 -0
- {python_hilo-2026.9.1 → python_hilo-2026.10.1}/doc/Challenge(Event) JSON/EventCHConsumptionUpdatedValuesReceived.json +0 -0
- {python_hilo-2026.9.1 → python_hilo-2026.10.1}/doc/Challenge(Event) JSON/EventCHDetailsInitialValuesReceived.json +0 -0
- {python_hilo-2026.9.1 → python_hilo-2026.10.1}/doc/Challenge(Event) JSON/EventCHDetailsUpdatedValuesReceived.json +0 -0
- {python_hilo-2026.9.1 → python_hilo-2026.10.1}/doc/Challenge(Event) JSON/EventFlexConsumptionUpdatedValuesReceived.json +0 -0
- {python_hilo-2026.9.1 → python_hilo-2026.10.1}/doc/Challenge(Event) JSON/EventFlexDetailsInitialValuesReceived.json +0 -0
- {python_hilo-2026.9.1 → python_hilo-2026.10.1}/doc/Challenge(Event) JSON/EventFlexDetailsUpdatedValuesReceived.json +0 -0
- {python_hilo-2026.9.1 → python_hilo-2026.10.1}/doc/Device Replies/DeviceListInitialValuesReceived.json +0 -0
- {python_hilo-2026.9.1 → python_hilo-2026.10.1}/doc/Old JSONs (pre 2025-26 season)/ChallengeAdded.json +0 -0
- {python_hilo-2026.9.1 → python_hilo-2026.10.1}/doc/Old JSONs (pre 2025-26 season)/ChallengeConsumptionUpdatedValuesReceived.json +0 -0
- {python_hilo-2026.9.1 → python_hilo-2026.10.1}/doc/Old JSONs (pre 2025-26 season)/ChallengeDetailsInitialValuesReceived.json +0 -0
- {python_hilo-2026.9.1 → python_hilo-2026.10.1}/doc/Old JSONs (pre 2025-26 season)/ChallengeListInitialValuesReceived.json +0 -0
- {python_hilo-2026.9.1 → python_hilo-2026.10.1}/doc/Old JSONs (pre 2025-26 season)/ChallengeListUpdatedValuesReceived.json +0 -0
- {python_hilo-2026.9.1 → python_hilo-2026.10.1}/doc/Postman/Hilo Prod.postman_environment.json +0 -0
- {python_hilo-2026.9.1 → python_hilo-2026.10.1}/doc/Postman/Hilo.postman_collection.json +0 -0
- {python_hilo-2026.9.1 → python_hilo-2026.10.1}/doc/Readme.md +0 -0
- {python_hilo-2026.9.1 → python_hilo-2026.10.1}/pyhilo/__init__.py +0 -0
- {python_hilo-2026.9.1 → python_hilo-2026.10.1}/pyhilo/device/__init__.py +0 -0
- {python_hilo-2026.9.1 → python_hilo-2026.10.1}/pyhilo/device/climate.py +0 -0
- {python_hilo-2026.9.1 → python_hilo-2026.10.1}/pyhilo/device/graphql_value_mapper.py +0 -0
- {python_hilo-2026.9.1 → python_hilo-2026.10.1}/pyhilo/device/light.py +0 -0
- {python_hilo-2026.9.1 → python_hilo-2026.10.1}/pyhilo/device/sensor.py +0 -0
- {python_hilo-2026.9.1 → python_hilo-2026.10.1}/pyhilo/device/switch.py +0 -0
- {python_hilo-2026.9.1 → python_hilo-2026.10.1}/pyhilo/devices.py +0 -0
- {python_hilo-2026.9.1 → python_hilo-2026.10.1}/pyhilo/event.py +0 -0
- {python_hilo-2026.9.1 → python_hilo-2026.10.1}/pyhilo/exceptions.py +0 -0
- {python_hilo-2026.9.1 → python_hilo-2026.10.1}/pyhilo/graphql.py +0 -0
- {python_hilo-2026.9.1 → python_hilo-2026.10.1}/pyhilo/oauth2helper.py +0 -0
- {python_hilo-2026.9.1 → python_hilo-2026.10.1}/pyhilo/signalr.py +0 -0
- {python_hilo-2026.9.1 → python_hilo-2026.10.1}/pyhilo/util/__init__.py +0 -0
- {python_hilo-2026.9.1 → python_hilo-2026.10.1}/tests/__init__.py +0 -0
- {python_hilo-2026.9.1 → python_hilo-2026.10.1}/tests/conftest.py +0 -0
- {python_hilo-2026.9.1 → python_hilo-2026.10.1}/tests/test_device.py +0 -0
- {python_hilo-2026.9.1 → python_hilo-2026.10.1}/tests/test_signalr.py +0 -0
- {python_hilo-2026.9.1 → python_hilo-2026.10.1}/tests/test_util.py +0 -0
- {python_hilo-2026.9.1 → python_hilo-2026.10.1}/tests/test_util_state.py +0 -0
|
@@ -24,7 +24,7 @@ jobs:
|
|
|
24
24
|
python-version: ${{ env.DEFAULT_PYTHON }}
|
|
25
25
|
|
|
26
26
|
- name: Install uv
|
|
27
|
-
uses: astral-sh/setup-uv@v10.0
|
|
27
|
+
uses: astral-sh/setup-uv@v10.2.0
|
|
28
28
|
|
|
29
29
|
- name: Install dependencies
|
|
30
30
|
run: uv sync --group dev
|
|
@@ -47,7 +47,7 @@ jobs:
|
|
|
47
47
|
python-version: ${{ env.DEFAULT_PYTHON }}
|
|
48
48
|
|
|
49
49
|
- name: Install uv
|
|
50
|
-
uses: astral-sh/setup-uv@v10.0
|
|
50
|
+
uses: astral-sh/setup-uv@v10.2.0
|
|
51
51
|
|
|
52
52
|
- name: Install dependencies
|
|
53
53
|
run: uv sync --group test
|
|
@@ -65,11 +65,12 @@ class API:
|
|
|
65
65
|
oauth_session: OAuth2Session,
|
|
66
66
|
request_retries: int = REQUEST_RETRY,
|
|
67
67
|
log_traces: bool = False,
|
|
68
|
+
state_yaml: str = DEFAULT_STATE_FILE,
|
|
68
69
|
) -> None:
|
|
69
70
|
"""Initialize"""
|
|
70
71
|
self._backoff_refresh_lock_api = asyncio.Lock()
|
|
71
72
|
self._request_retries = request_retries
|
|
72
|
-
self._state_yaml: str =
|
|
73
|
+
self._state_yaml: str = state_yaml
|
|
73
74
|
self.state: StateDict = {}
|
|
74
75
|
self.async_request = self._wrap_request_method(self._request_retries)
|
|
75
76
|
self.device_attributes = get_device_attributes()
|
|
@@ -92,6 +93,7 @@ class API:
|
|
|
92
93
|
oauth_session: OAuth2Session,
|
|
93
94
|
request_retries: int = REQUEST_RETRY,
|
|
94
95
|
log_traces: bool = False,
|
|
96
|
+
state_yaml: str = DEFAULT_STATE_FILE,
|
|
95
97
|
) -> API:
|
|
96
98
|
"""Get an authenticated API object.
|
|
97
99
|
:param session: The ``aiohttp`` ``ClientSession`` session used for all HTTP requests
|
|
@@ -100,6 +102,7 @@ class API:
|
|
|
100
102
|
:type oauth_session: ``config_entry_oauth2_flow.OAuth2Session``
|
|
101
103
|
:param request_retries: The default number of request retries to use
|
|
102
104
|
:type request_retries: ``int``
|
|
105
|
+
:param state_yaml: Path of the file where the API state (tokens, etc.) is saved.
|
|
103
106
|
:rtype: :meth:`pyhilo.api.API`
|
|
104
107
|
"""
|
|
105
108
|
api = cls(
|
|
@@ -107,6 +110,7 @@ class API:
|
|
|
107
110
|
oauth_session=oauth_session,
|
|
108
111
|
request_retries=request_retries,
|
|
109
112
|
log_traces=log_traces,
|
|
113
|
+
state_yaml=state_yaml,
|
|
110
114
|
)
|
|
111
115
|
# Test token before post init
|
|
112
116
|
await api.async_get_access_token()
|
|
@@ -11,7 +11,7 @@ INSTANCE_ID: Final = str(uuid.uuid4())[24:]
|
|
|
11
11
|
LOG: Final = logging.getLogger(__package__)
|
|
12
12
|
DEFAULT_STATE_FILE: Final = "hilo_state.yaml"
|
|
13
13
|
REQUEST_RETRY: Final = 9
|
|
14
|
-
PYHILO_VERSION: Final = "2026.
|
|
14
|
+
PYHILO_VERSION: Final = "2026.10.01"
|
|
15
15
|
# TODO: Find a way to keep previous line in sync with pyproject.toml automatically
|
|
16
16
|
|
|
17
17
|
CONTENT_TYPE_FORM: Final = "application/x-www-form-urlencoded"
|
|
@@ -115,6 +115,15 @@ def _write_state(state_yaml: str, state: dict[str, Any] | StateDict) -> None:
|
|
|
115
115
|
os.replace(tmp_path, state_yaml)
|
|
116
116
|
|
|
117
117
|
|
|
118
|
+
async def _async_write_state(
|
|
119
|
+
state_yaml: str, state: dict[str, Any] | StateDict
|
|
120
|
+
) -> None:
|
|
121
|
+
"""Run _write_state in a worker thread so it doesn't block the event loop."""
|
|
122
|
+
await asyncio.get_running_loop().run_in_executor(
|
|
123
|
+
None, _write_state, state_yaml, state
|
|
124
|
+
)
|
|
125
|
+
|
|
126
|
+
|
|
118
127
|
async def get_state(state_yaml: str, _already_locked: bool = False) -> StateDict:
|
|
119
128
|
"""Read in state yaml.
|
|
120
129
|
|
|
@@ -143,10 +152,10 @@ async def get_state(state_yaml: str, _already_locked: bool = False) -> StateDict
|
|
|
143
152
|
)
|
|
144
153
|
defaults = _get_defaults(StateDict)
|
|
145
154
|
if _already_locked:
|
|
146
|
-
|
|
155
|
+
await _async_write_state(state_yaml, defaults)
|
|
147
156
|
else:
|
|
148
157
|
async with lock:
|
|
149
|
-
|
|
158
|
+
await _async_write_state(state_yaml, defaults)
|
|
150
159
|
return defaults
|
|
151
160
|
|
|
152
161
|
return state_yaml_payload
|
|
@@ -159,10 +168,10 @@ async def get_state(state_yaml: str, _already_locked: bool = False) -> StateDict
|
|
|
159
168
|
)
|
|
160
169
|
defaults = _get_defaults(StateDict)
|
|
161
170
|
if _already_locked:
|
|
162
|
-
|
|
171
|
+
await _async_write_state(state_yaml, defaults)
|
|
163
172
|
else:
|
|
164
173
|
async with lock:
|
|
165
|
-
|
|
174
|
+
await _async_write_state(state_yaml, defaults)
|
|
166
175
|
return defaults
|
|
167
176
|
|
|
168
177
|
|
|
@@ -186,7 +195,4 @@ async def set_state(
|
|
|
186
195
|
merged_state: dict[str, Any] = {key: {**current_state.get(key, {}), **state}} # type: ignore[dict-item]
|
|
187
196
|
new_state: dict[str, Any] = {**current_state, **merged_state}
|
|
188
197
|
LOG.debug("Saving state to yaml file")
|
|
189
|
-
|
|
190
|
-
# to the file in a non blocking manner. Currently, yaml.dump is
|
|
191
|
-
# synchronous on the main event loop.
|
|
192
|
-
_write_state(state_yaml, new_state)
|
|
198
|
+
await _async_write_state(state_yaml, new_state)
|