Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
12 changes: 5 additions & 7 deletions .github/workflows/pythonpackage.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -15,16 +15,14 @@ jobs:

steps:
- uses: actions/checkout@v7
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v7
- name: Install uv
uses: astral-sh/setup-uv@v10.3.2
with:
python-version: ${{ matrix.python-version }}
enable-cache: true

- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install -r requirements.test.txt
run: uv sync --locked

- name: Run pytest
run: |
pytest
run: uv run pytest
1 change: 0 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,5 @@ coverage.xml
.mypy_cache/

# Local environments
.python-version
.venv/
venv/
28 changes: 6 additions & 22 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -1,16 +1,12 @@
repos:
- repo: https://github.com/asottile/pyupgrade
rev: v3.22.0
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.17.2
hooks:
- id: pyupgrade
args: [--py314-plus]
- repo: https://github.com/psf/black
rev: 26.10.1
hooks:
- id: black
- id: ruff-check
args:
- --safe
- --quiet
- --fix
files: ^((custom_components|tests)/.+)?[^/]+\.py$
- id: ruff-format
files: ^((custom_components|tests)/.+)?[^/]+\.py$
- repo: https://github.com/codespell-project/codespell
rev: v2.4.3
Expand All @@ -21,14 +17,6 @@ repos:
- --skip="./.*,*.csv,*.json"
- --quiet-level=2
exclude_types: [csv, json]
- repo: https://github.com/PyCQA/flake8
rev: 7.4.1
hooks:
- id: flake8
additional_dependencies:
- flake8-docstrings==1.7.0
- pydocstyle==6.3.0
files: ^(custom_components|tests)/.+\.py$
- repo: https://github.com/PyCQA/bandit
rev: 1.9.4
hooks:
Expand All @@ -38,10 +26,6 @@ repos:
- --format=custom
- --configfile=tests/bandit.yaml
files: ^(custom_components|tests)/.+\.py$
- repo: https://github.com/PyCQA/isort
rev: 9.0.2
hooks:
- id: isort
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v6.0.0
hooks:
Expand Down
1 change: 1 addition & 0 deletions .python-version
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
3.14
18 changes: 9 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,23 +25,23 @@ Requires Home Assistant 2024.11.0 or newer.

## Running Tests

The test suite requires Python 3.14, the version required by current releases of Home Assistant. Create a virtualenv
(I recommend checking out [pyenv](https://github.com/pyenv/pyenv) and [pyenv-virtualenv](https://github.com/pyenv/pyenv-virtualenv)
for this) and install the test requirements.
The test suite requires Python 3.14, the version required by current releases of Home Assistant. Dependencies are
managed with [uv](https://docs.astral.sh/uv/), which will download a suitable Python and create a virtualenv for you.
Install the dependencies (including the test and lint tools) with:

```bash
$ pip install -r requirements.test.txt
$ uv sync
```

After the test dependencies are installed you can simply invoke `pytest` to run
After the dependencies are installed you can invoke `pytest` through uv to run
the test suite.

```bash
$ pytest
$ uv run pytest
============================= test session starts ==============================
platform linux -- Python 3.14.8, pytest-9.0.3, pluggy-1.7.0
rootdir: /home/aaron/projects/github-custom-component-tutorial
configfile: setup.cfg
configfile: pyproject.toml
testpaths: tests
plugins: codspeed-5.0.3, aiohttp-1.1.1, homeassistant-custom-component-0.13.374, xdist-3.8.0, asyncio-1.4.0, cov-7.1.0, anyio-4.15.1, timeout-2.4.0, pytest_freezer-0.4.9, respx-0.23.1, github-actions-annotate-failures-0.4.2, picked-0.5.1, requests-mock-1.12.1, socket-0.8.1, unordered-0.8.0, syrupy-6.1.1
asyncio: mode=Mode.AUTO, debug=False, asyncio_default_fixture_loop_scope=function, asyncio_default_test_loop_scope=function
Expand Down Expand Up @@ -71,11 +71,11 @@ Required test coverage of 84.0% reached. Total coverage: 87.56%
Linting and formatting checks are run with [pre-commit](https://pre-commit.com/). To run them against the whole repo:

```bash
$ pre-commit run --all-files
$ uv run pre-commit run --all-files
```

To have them run automatically on every commit:

```bash
$ pre-commit install
$ uv run pre-commit install
```
2 changes: 1 addition & 1 deletion custom_components/github_custom/sensor.py
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,7 @@ async def async_update(self) -> None:
# Set state to short commit sha.
self._state = latest_commit["sha"][:7]
self._available = True
except (ClientError, gidgethub.GitHubException):
except ClientError, gidgethub.GitHubException:
self._available = False
_LOGGER.exception(
"Error retrieving data from GitHub for sensor %s", self.name
Expand Down
83 changes: 83 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
[project]
name = "github-custom-component-tutorial"
version = "0.1.0"
description = "Home Assistant custom component created in the aarongodfrey.dev tutorial series"
readme = "README.md"
license = "MIT"
requires-python = ">=3.14.2"
dependencies = [
# From our manifest.json for our custom component
"gidgethub[aiohttp]==6.0.0",
]

[dependency-groups]
dev = [
# Pinned to match homeassistant's own pin
"cryptography==50.0.1",
"pre-commit",
# Strictly for tests. This also pins homeassistant, pytest, pytest-asyncio,
# pytest-cov and coverage to the versions HA itself tests with.
"pytest-homeassistant-custom-component==0.13.374",
# Ubuntu 26.04 runners no longer ship legacy zones (e.g. US/Pacific) used by the HA test harness
"tzdata",
]

[tool.uv]
# This repo is a Home Assistant custom component, not an installable package
package = false

[tool.ruff]
line-length = 88

[tool.ruff.lint]
select = [
"D", # pydocstyle
"E", # pycodestyle errors
"F", # pyflakes
"I", # isort
"UP", # pyupgrade
"W", # pycodestyle warnings
]
ignore = [
"D202", # No blank lines allowed after function docstring
"E501", # Line too long, handled by the formatter
]

[tool.ruff.lint.pydocstyle]
convention = "pep257"

[tool.ruff.lint.isort]
# will group `import x` and `from x import` of the same module.
force-sort-within-sections = true
known-first-party = ["custom_components", "tests"]
forced-separate = ["tests"]
combine-as-imports = true

[tool.pytest.ini_options]
testpaths = ["tests"]
norecursedirs = [".git"]
addopts = "--cov=custom_components"
asyncio_mode = "auto"
asyncio_default_fixture_loop_scope = "function"

[tool.coverage.run]
source = ["custom_components"]

[tool.coverage.report]
exclude_lines = [
"pragma: no cover",
"raise NotImplemented()",
"if __name__ == '__main__':",
"main()",
]
fail_under = 84
show_missing = true

[tool.mypy]
python_version = "3.14"
ignore_errors = true
follow_imports = "silent"
ignore_missing_imports = true
warn_incomplete_stub = true
warn_redundant_casts = true
warn_unused_configs = true
10 changes: 0 additions & 10 deletions requirements.test.txt

This file was deleted.

62 changes: 0 additions & 62 deletions setup.cfg

This file was deleted.

Loading
Loading