Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
7ec2130
move to uv
adamlogan73 Mar 22, 2026
c317706
Replace mypy with zuban and relax development dependency versions
adamlogan73 Mar 23, 2026
f9d4111
Streamline Docker build and merge dev dependency groups
adamlogan73 Mar 30, 2026
fb7da56
Flatten client hierarchy and remove Raw prefix
adamlogan73 Mar 30, 2026
436f747
Split models into Base/Sync/Async hierarchies and modernize codebase
adamlogan73 Apr 1, 2026
e7dec40
Replace Processing class with standalone sync/async functions
adamlogan73 Apr 1, 2026
74f79a6
Add unit tests for client params, error classes, and models
adamlogan73 Apr 1, 2026
357102d
Unify client API surface across REST and WebSocket clients
adamlogan73 Apr 1, 2026
24a8a25
Add entity registry methods and models for WebSocket clients
adamlogan73 Apr 2, 2026
821c20e
Update documentation and docstrings for v2 API surface
adamlogan73 Apr 2, 2026
efef0a9
Fix bugs and issues found during full code review
adamlogan73 Apr 3, 2026
f30fa11
Fix websocket error handling and test failures
adamlogan73 Apr 3, 2026
f24678a
Add v2.0 changelog
adamlogan73 Apr 3, 2026
3517ad6
Bump version to v6.0.0
adamlogan73 Apr 3, 2026
c8187ce
Migrate from requests/aiohttp/websockets to niquests
adamlogan73 Apr 5, 2026
fdb5996
Bump readthedocs Python version from 3.10 to 3.11
GrandMoff100 Apr 6, 2026
e901829
Add command to check Python and pip paths
GrandMoff100 Apr 6, 2026
a67c1a3
Fix not installing to readthedocs venv
GrandMoff100 Apr 6, 2026
d7ed02f
Fix some typing issues
GrandMoff100 Apr 6, 2026
7e3a01b
Ignore intentionally unreachable line
GrandMoff100 Apr 6, 2026
2de2990
Use CaseInsensitiveDict for headers in mock responses
GrandMoff100 Apr 7, 2026
52d76ab
Pin urllib3-future<2.19.902 to avoid WebSocket regression
adamlogan73 Apr 7, 2026
6c6e74c
Unpin urllib3.future after websockets patched
GrandMoff100 Apr 8, 2026
0bd97cf
Replace mypy with zuban: add pre-commit hook, convert [tool.mypy] to …
adamlogan73 Apr 9, 2026
03351fd
Exclude type guard error messages from coverage
GrandMoff100 Apr 12, 2026
16ed85d
Exclude testing session start error handling and remove unnecessary e…
GrandMoff100 Apr 12, 2026
81adb38
Fix coverage gaps: restore pragma: no cover, annotate untestable bran…
adamlogan73 Apr 13, 2026
2a7a677
Improve usability of config/entity_registry/update parameters (#235)
mj23000 Apr 26, 2026
e5c7152
Fix aliases typing (#234)
mj23000 Apr 26, 2026
be2ec71
Modernize StrEnum usage (#233)
mj23000 Apr 26, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 6 additions & 10 deletions .github/workflows/python-publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,16 +16,12 @@ jobs:
uses: actions/setup-python@v2
with:
python-version: "3.13"
- name: Install uv
uses: astral-sh/setup-uv@v4
- name: Install dependencies
run: |
python -m pip install --upgrade pip poetry
poetry config virtualenvs.create false
poetry install

- name: build release distributions
run: |
# NOTE: put your own distribution build steps here.
poetry build
run: uv sync
- name: Build release distributions
run: uv build

- name: upload dists
uses: actions/upload-artifact@v4
Expand All @@ -48,4 +44,4 @@ jobs:
path: dist/

- name: Publish release distributions to PyPI
uses: pypa/gh-action-pypi-publish@release/v1
uses: pypa/gh-action-pypi-publish@release/v1
18 changes: 8 additions & 10 deletions .github/workflows/test-suite.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,13 @@ on:
paths:
- "**.py"
- "pyproject.toml"
- "poetry.lock"
pull_request:
branches:
- master
- dev
paths:
- "**.py"
- "pyproject.toml"
- "poetry.lock"
workflow_dispatch:

jobs:
Expand All @@ -23,21 +21,21 @@ jobs:
- name: Setup Python
uses: actions/setup-python@v3
with:
python-version: "3.9"
python-version: "3.11"
- name: Checkout
uses: actions/checkout@v3
with:
ref: ${{ github.event.pull_request.head.sha }}
- name: Install uv
uses: astral-sh/setup-uv@v4
- name: Install Dependencies
run: |
pip install poetry
poetry install --with styling
run: uv sync --group dev
- name: Run Ruff format
run: poetry run ruff format homeassistant_api
run: uv run ruff format homeassistant_api
- name: Run Ruff linting
run: poetry run ruff check homeassistant_api
- name: Run MyPy
run: poetry run mypy homeassistant_api --show-error-codes
run: uv run ruff check homeassistant_api
- name: Run Zuban
run: uv run zuban check homeassistant_api

code_functionality:
name: "Code Functionality"
Expand Down
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
CHANGELOG.draft.md

# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
Expand Down Expand Up @@ -133,6 +135,8 @@ venv/
ENV/
env.bak/
venv.bak/
uv.lock
poetry.lock

# Spyder project settings
.spyderproject
Expand Down
13 changes: 7 additions & 6 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
repos:
- repo: https://github.com/pre-commit/mirrors-mypy
Comment thread
GrandMoff100 marked this conversation as resolved.
- repo: local
hooks:
- id: mypy
additional_dependencies:
- types-requests
- types-simplejson
rev: "v1.17.1"
- id: zuban
name: zuban
entry: uv run zuban check homeassistant_api
language: system
types: [python]
pass_filenames: false
- repo: https://github.com/pre-commit/pre-commit-hooks
hooks:
- id: trailing-whitespace
Expand Down
10 changes: 3 additions & 7 deletions .readthedocs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,11 @@ version: 2
build:
os: ubuntu-22.04
tools:
python: "3.10"
python: "3.11"
jobs:
pre_create_environment:
- asdf plugin add poetry
- asdf install poetry 1.8.3
- asdf global poetry 1.8.3
- poetry export -f requirements.txt --output requirements.txt --with docs
post_install:
- pip install -r requirements.txt
- pip install uv
- uv export --group docs --no-hashes | uv pip install -r -

# Build documentation in the docs/ directory with Sphinx
sphinx:
Expand Down
57 changes: 57 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
# HomeAssistant-API v6.0 Changelog

## Breaking Changes
A lot has changed in this version. A lot went into modernising and standardizing the interfaces of the clients.
As such, many of the previous paradigms have changed. If you run into any bugs or issues, please let us know.
### Minimum Python version raised to 3.11
Python 3.9 and 3.10 are no longer supported.

### Client classes restructured
The old `Client` class (which combined sync and async via a `use_async` flag) has been removed. There are now four distinct client classes:

| Old | New |
|---|---|
| `Client(use_async=False)` | `Client` |
| `Client(use_async=True)` | `AsyncClient` |
| `WebsocketClient` (sync) | `WebsocketClient` |
| — | `AsyncWebsocketClient` (new) |

Async client methods no longer have the `async_` prefix — e.g. `async_get_states()` is now just `get_states()` on `AsyncClient`.

### Models split into Base/Sync/Async variants
`Domain`, `Entity`, `Group`, `Service`, and `Event` now have three variants each:
- **`Base*`** — plain data, no client reference
- **`*`** (e.g. `Domain`) — sync, bound to `Client`
- **`Async*`** (e.g. `AsyncDomain`) — async, bound to `AsyncClient`

### Processing module rewritten
The decorator-based `@Processing.processor(mimetype)` registry has been replaced with simple dict-based MIME dispatch and separate `sync`/`async` entry points. Custom processor registration and the `decode_bytes` parameter have been removed.

### Build system moved from Poetry to uv + hatchling
`poetry.lock` is removed. The project now uses `uv` for dependency management and `hatchling` as the build backend.

### Type checker changed from mypy to zuban

Comment thread
GrandMoff100 marked this conversation as resolved.
## New Features

### WebSocket API support (sync & async)
Full WebSocket client implementation for both sync (`WebsocketClient`) and async (`AsyncWebsocketClient`) with support for:
- **Config entries** — get, disable, enable, ignore flow, subentries, subscribe
- **Entity registry** — list, get, update, remove entries
- **Events** — subscribe, fire, and listen
- **Services** — trigger with full domain/service routing
- **Templates** — render and subscribe to template updates

### Entity registry models
New models: `EntityRegistryEntry`, `EntityRegistryEntryExtended`, `EntityRegistryUpdateResult`.

### Configurable WebSocket max message size
WS clients accept a `max_size` parameter (default 16 MB) to handle large responses like full entity registry lists.

## Improvements

- Unified method signatures across all four client classes for consistency
- Expanded ruff lint rules to `ALL` (from just E, F, W)
- Test coverage improved to ~99%
- Modernized type annotations throughout
- Response content is now read lazily, eliminating internal `_buffer` access hacks
23 changes: 8 additions & 15 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,20 +1,13 @@
ARG BUILD_FROM
FROM ghcr.io/astral-sh/uv:python3.13-bookworm AS dependencies
WORKDIR /app
COPY pyproject.toml README.md ./
RUN uv sync --group dev

FROM ${BUILD_FROM} AS base
FROM python:3.13-bookworm
ENV PYTHONPATH=.
WORKDIR /app
COPY ./ /app/

FROM base AS dependencies
RUN pip install --upgrade pip wheel
RUN pip install poetry
RUN python3 -m venv .venv && \
. .venv/bin/activate && \
poetry install --with testing && \
deactivate

FROM base AS final
COPY --from=dependencies /app/.venv /app/.venv
ENV PATH="/app/.venv/bin:$PATH"
COPY ./ /app/

ENTRYPOINT [ "sh", "entrypoint.sh" ]

ENTRYPOINT [ "sh", "entrypoint.sh" ]
19 changes: 7 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,25 +25,22 @@ with Client(
'<API Server URL>', # i.e. 'http://homeassistant.local:8123/api/'
'<Your Long Lived Access-Token>'
) as client:
light = client.trigger_service('light', 'turn_on', entity_id="light.living_room")
client.trigger_service('light', 'turn_on', entity_id="light.living_room")
```

All the methods also support async/await!
Just prefix the method with `async_` and pass the `use_async=True` argument to the `Client` constructor.
Then you can use the methods as coroutines
(i.e. `await light.async_turn_on(...)`).
All four client classes share the same method names.
The async clients (`AsyncClient`, `AsyncWebsocketClient`) use `async def` methods that you `await`.

```py
import asyncio
from homeassistant_api import Client
from homeassistant_api import AsyncClient

async def main():
with Client(
async with AsyncClient(
'<REST API Server URL>', # i.e. 'http://homeassistant.local:8123/api/'
'<Your Long Lived Access-Token>',
use_async=True
) as client:
light = await client.async_trigger_service('light', 'turn_on', entity_id="light.living_room")
await client.trigger_service('light', 'turn_on', entity_id="light.living_room")

asyncio.run(main())
```
Expand All @@ -57,11 +54,9 @@ with WebsocketClient(
'<WS API Server URL>', # i.e. 'ws://homeassistant.local:8123/api/websocket'
'<Your Long Lived Access-Token>'
) as ws_client:
light = ws_client.trigger_service('light', 'turn_on', entity_id="light.living_room")
ws_client.trigger_service('light', 'turn_on', entity_id="light.living_room")
```

> Note: The Websocket API is not yet supported in async/await mode.

## Documentation

All documentation, API reference, contribution guidelines and pretty much everything else
Expand Down
2 changes: 0 additions & 2 deletions compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,6 @@ services:
tests:
build:
context: .
args:
BUILD_FROM: "python:3.13"
image: homeassistant-tests:latest
volumes:
- ./volumes/coverage:/app/coverage:rw
Expand Down
12 changes: 6 additions & 6 deletions docs/CONTRIBUTING.rst
Original file line number Diff line number Diff line change
Expand Up @@ -37,12 +37,12 @@ Next run in your terminal.
Step Three: Installing Dependencies
======================================

Firstly, you need to have Python 3.7 or newer with Pip installed.
Firstly, you need to have Python 3.11 or newer installed.
Download the latest Python Version from `here <https://www.python.org/>`__.
Then you need to install the very popular Python Package Manager, :code:`poetry`.
Checkout the `Poetry Docs <https://python-poetry.org/docs/>`__.
You can install that with :code:`pip` by running :code:`pip install poetry`.
Now you can install the project's dependencies by running :code:`cd HomeAssistantAPI && poetry install`
Then you need to install :code:`uv`, a fast Python package manager.
Checkout the `uv Docs <https://docs.astral.sh/uv/>`__.
You can install it with :code:`pip` by running :code:`pip install uv`, or see the uv docs for other installation methods.
Now you can install the project's dependencies by running :code:`cd HomeAssistantAPI && uv sync`

Step Four: [Optional] Setting Up a Home Assistant Development Environment.
=============================================================================
Expand All @@ -69,7 +69,7 @@ Code Styling Guidelines
In order to make sure that our code is easy to read, and navigate.
As well as to stop stupid mistakes like typos, undefined variables, etc.
We enforce code standards.
Using the tools, :code:`ruff`, :code:`pytest`, and :code:`docker`, we make make sure that our code quality is top notch, and that are changes work everywhere.
Using the tools, :code:`ruff`, :code:`zuban`, :code:`pytest`, and :code:`docker`, we make make sure that our code quality is top notch, and that are changes work everywhere.
You can those tools manually yourself, but they also run automatically when you open a PR.

Merging Your Contributions
Expand Down
Loading
Loading