Skip to content

Commit 6882ba7

Browse files
author
jekalmin
committed
Add Tests
1 parent 309737f commit 6882ba7

File tree

18 files changed

+1923
-91
lines changed

18 files changed

+1923
-91
lines changed

.github/workflows/ci.yml

Lines changed: 186 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,186 @@
1+
name: ci
2+
3+
on:
4+
pull_request:
5+
push:
6+
branches:
7+
- main
8+
- develop
9+
schedule:
10+
- cron: "0 0 * * *"
11+
12+
concurrency:
13+
group: ${{ github.workflow }}-${{ github.ref }}
14+
cancel-in-progress: true
15+
16+
env:
17+
HA_CORE_REPO: "home-assistant/core"
18+
HA_CORE_BRANCH: "dev"
19+
20+
jobs:
21+
prepare:
22+
name: Prepare versions from HA core
23+
runs-on: ubuntu-latest
24+
outputs:
25+
python-version: ${{ steps.get-versions.outputs.python-version }}
26+
openai-version: ${{ steps.get-versions.outputs.openai-version }}
27+
hassil-version: ${{ steps.get-versions.outputs.hassil-version }}
28+
home-assistant-intents-version: ${{ steps.get-versions.outputs.home-assistant-intents-version }}
29+
xmltodict-version: ${{ steps.get-versions.outputs.xmltodict-version }}
30+
beautifulsoup4-version: ${{ steps.get-versions.outputs.beautifulsoup4-version }}
31+
lxml-version: ${{ steps.get-versions.outputs.lxml-version }}
32+
steps:
33+
- name: Get versions from Home Assistant core
34+
id: get-versions
35+
run: |
36+
# Function to extract package version from manifest
37+
get_package_version() {
38+
local manifest="$1"
39+
local package="$2"
40+
echo "$manifest" | grep -o "\"$package==[^\"]*\"" | sed "s/\"$package==//;s/\"//"
41+
}
42+
43+
# Get Python version from HA core
44+
PYTHON_VERSION=$(curl -fsSL https://raw.githubusercontent.com/${{ env.HA_CORE_REPO }}/${{ env.HA_CORE_BRANCH }}/.python-version | tr -d '\n')
45+
echo "python-version=$PYTHON_VERSION" >> $GITHUB_OUTPUT
46+
echo "Python version from HA core: $PYTHON_VERSION"
47+
48+
# Get openai_conversation dependencies
49+
OPENAI_MANIFEST=$(curl -fsSL https://raw.githubusercontent.com/${{ env.HA_CORE_REPO }}/${{ env.HA_CORE_BRANCH }}/homeassistant/components/openai_conversation/manifest.json)
50+
OPENAI_VERSION=$(get_package_version "$OPENAI_MANIFEST" "openai")
51+
echo "openai-version=$OPENAI_VERSION" >> $GITHUB_OUTPUT
52+
echo "openai version from HA core: $OPENAI_VERSION"
53+
54+
# Get conversation dependencies
55+
CONVERSATION_MANIFEST=$(curl -fsSL https://raw.githubusercontent.com/${{ env.HA_CORE_REPO }}/${{ env.HA_CORE_BRANCH }}/homeassistant/components/conversation/manifest.json)
56+
HASSIL_VERSION=$(get_package_version "$CONVERSATION_MANIFEST" "hassil")
57+
echo "hassil-version=$HASSIL_VERSION" >> $GITHUB_OUTPUT
58+
echo "hassil version from HA core: $HASSIL_VERSION"
59+
60+
HA_INTENTS_VERSION=$(get_package_version "$CONVERSATION_MANIFEST" "home-assistant-intents")
61+
echo "home-assistant-intents-version=$HA_INTENTS_VERSION" >> $GITHUB_OUTPUT
62+
echo "home-assistant-intents version from HA core: $HA_INTENTS_VERSION"
63+
64+
# Get rest dependencies
65+
REST_MANIFEST=$(curl -fsSL https://raw.githubusercontent.com/${{ env.HA_CORE_REPO }}/${{ env.HA_CORE_BRANCH }}/homeassistant/components/rest/manifest.json)
66+
XMLTODICT_VERSION=$(get_package_version "$REST_MANIFEST" "xmltodict")
67+
echo "xmltodict-version=$XMLTODICT_VERSION" >> $GITHUB_OUTPUT
68+
echo "xmltodict version from HA core: $XMLTODICT_VERSION"
69+
70+
# Get scrape dependencies
71+
SCRAPE_MANIFEST=$(curl -fsSL https://raw.githubusercontent.com/${{ env.HA_CORE_REPO }}/${{ env.HA_CORE_BRANCH }}/homeassistant/components/scrape/manifest.json)
72+
BS4_VERSION=$(get_package_version "$SCRAPE_MANIFEST" "beautifulsoup4")
73+
echo "beautifulsoup4-version=$BS4_VERSION" >> $GITHUB_OUTPUT
74+
echo "beautifulsoup4 version from HA core: $BS4_VERSION"
75+
76+
LXML_VERSION=$(get_package_version "$SCRAPE_MANIFEST" "lxml")
77+
echo "lxml-version=$LXML_VERSION" >> $GITHUB_OUTPUT
78+
echo "lxml version from HA core: $LXML_VERSION"
79+
lint:
80+
name: Lint
81+
runs-on: ubuntu-latest
82+
needs: prepare
83+
steps:
84+
- name: Checkout repository
85+
uses: actions/checkout@v4
86+
87+
- name: Set up Python ${{ needs.prepare.outputs.python-version }}
88+
uses: actions/setup-python@v5
89+
with:
90+
python-version: ${{ needs.prepare.outputs.python-version }}
91+
92+
- name: Install dependencies
93+
run: |
94+
python -m pip install --upgrade pip
95+
pip install ruff
96+
97+
- name: Run Ruff linter
98+
run: ruff check custom_components/
99+
100+
- name: Run Ruff formatter check
101+
run: ruff format --check custom_components/
102+
103+
type-check:
104+
name: Type Check
105+
runs-on: ubuntu-latest
106+
needs: prepare
107+
steps:
108+
- name: Checkout repository
109+
uses: actions/checkout@v4
110+
111+
- name: Set up Python ${{ needs.prepare.outputs.python-version }}
112+
uses: actions/setup-python@v5
113+
with:
114+
python-version: ${{ needs.prepare.outputs.python-version }}
115+
116+
- name: Install dependencies
117+
run: |
118+
python -m pip install --upgrade pip
119+
# Install dependencies with versions from HA core
120+
pip install \
121+
"openai==${{ needs.prepare.outputs.openai-version }}" \
122+
"hassil==${{ needs.prepare.outputs.hassil-version }}" \
123+
"home-assistant-intents==${{ needs.prepare.outputs.home-assistant-intents-version }}" \
124+
"xmltodict==${{ needs.prepare.outputs.xmltodict-version }}" \
125+
"beautifulsoup4==${{ needs.prepare.outputs.beautifulsoup4-version }}" \
126+
"lxml==${{ needs.prepare.outputs.lxml-version }}"
127+
pip install -r requirements_test.txt
128+
pip install mypy
129+
130+
- name: Run MyPy
131+
run: mypy custom_components/extended_openai_conversation
132+
133+
test:
134+
name: Test (HA ${{ matrix.home-assistant }})
135+
runs-on: ubuntu-latest
136+
needs: prepare
137+
strategy:
138+
fail-fast: false
139+
matrix:
140+
home-assistant:
141+
- "stable"
142+
- "dev"
143+
steps:
144+
- name: Checkout repository
145+
uses: actions/checkout@v4
146+
147+
- name: Set up Python ${{ needs.prepare.outputs.python-version }}
148+
uses: actions/setup-python@v5
149+
with:
150+
python-version: ${{ needs.prepare.outputs.python-version }}
151+
allow-prereleases: true
152+
153+
- name: Install dependencies
154+
run: |
155+
python -m pip install --upgrade pip
156+
# Install dependencies with versions from HA core
157+
pip install \
158+
"openai==${{ needs.prepare.outputs.openai-version }}" \
159+
"hassil==${{ needs.prepare.outputs.hassil-version }}" \
160+
"home-assistant-intents==${{ needs.prepare.outputs.home-assistant-intents-version }}" \
161+
"xmltodict==${{ needs.prepare.outputs.xmltodict-version }}" \
162+
"beautifulsoup4==${{ needs.prepare.outputs.beautifulsoup4-version }}" \
163+
"lxml==${{ needs.prepare.outputs.lxml-version }}"
164+
pip install -r requirements_test.txt
165+
166+
- name: Install Home Assistant stable
167+
if: matrix.home-assistant == 'stable'
168+
run: |
169+
pip install homeassistant
170+
171+
- name: Install Home Assistant dev
172+
if: matrix.home-assistant == 'dev'
173+
run: |
174+
pip install --upgrade git+https://github.com/home-assistant/core.git@dev
175+
176+
- name: Run tests
177+
env:
178+
PYTHONPATH: ${{ github.workspace }}
179+
run: |
180+
pytest tests/ \
181+
-v \
182+
--asyncio-mode=auto \
183+
--timeout=30 \
184+
--cov=custom_components/extended_openai_conversation \
185+
--cov-report=xml \
186+
--cov-report=term-missing
Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,17 @@
1-
name: Validate
1+
name: hacs
22

33
on:
44
push:
55
pull_request:
66
schedule:
77
- cron: "0 0 * * *"
8-
workflow_dispatch:
98

109
jobs:
10+
validate:
11+
runs-on: "ubuntu-latest"
12+
steps:
13+
- uses: "actions/checkout@v4"
14+
- uses: "home-assistant/actions/hassfest@master"
1115
validate-hacs:
1216
runs-on: "ubuntu-latest"
1317
steps:

.github/workflows/hassfest.yaml

Lines changed: 0 additions & 14 deletions
This file was deleted.

.gitignore

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
# Python
2+
__pycache__/
3+
*.py[cod]
4+
*$py.class
5+
*.so
6+
.Python
7+
build/
8+
develop-eggs/
9+
dist/
10+
downloads/
11+
eggs/
12+
.eggs/
13+
lib/
14+
lib64/
15+
parts/
16+
sdist/
17+
var/
18+
wheels/
19+
*.egg-info/
20+
.installed.cfg
21+
*.egg
22+
23+
# Virtual environments
24+
.venv/
25+
venv/
26+
ENV/
27+
env/
28+
29+
# IDE
30+
.vscode/
31+
.idea/
32+
*.swp
33+
*.swo
34+
*~
35+
36+
# Testing
37+
.pytest_cache/
38+
.coverage
39+
htmlcov/
40+
*.cover
41+
.hypothesis/
42+
coverage.xml
43+
44+
# OS
45+
.DS_Store
46+
Thumbs.db

custom_components/extended_openai_conversation/__init__.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,14 @@
44

55
import logging
66

7-
from openai import AsyncClient
8-
from openai._exceptions import AuthenticationError, OpenAIError
9-
107
from homeassistant.config_entries import ConfigEntry, ConfigSubentry
118
from homeassistant.const import CONF_API_KEY, Platform
129
from homeassistant.core import HomeAssistant
1310
from homeassistant.exceptions import ConfigEntryNotReady
1411
from homeassistant.helpers import config_validation as cv
1512
from homeassistant.helpers.typing import ConfigType
13+
from openai import AsyncClient
14+
from openai._exceptions import AuthenticationError, OpenAIError
1615

1716
from .const import (
1817
CONF_API_PROVIDER,

custom_components/extended_openai_conversation/config_flow.py

Lines changed: 12 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,6 @@
66
import types
77
from typing import Any
88

9-
from openai._exceptions import APIConnectionError, AuthenticationError
10-
import voluptuous as vol
11-
import yaml
12-
139
from homeassistant.config_entries import (
1410
ConfigEntry,
1511
ConfigEntryState,
@@ -31,6 +27,9 @@
3127
SelectSelectorMode,
3228
TemplateSelector,
3329
)
30+
from openai._exceptions import APIConnectionError, AuthenticationError
31+
import voluptuous as vol
32+
import yaml
3433

3534
from .const import (
3635
API_PROVIDERS,
@@ -296,12 +295,11 @@ async def async_step_advanced(
296295
"""Handle advanced options step."""
297296
if user_input is not None:
298297
# Merge advanced options with temp data
299-
final_data = {**self._temp_data, **user_input}
298+
final_data = {**(self._temp_data or {}), **user_input}
300299

301300
if self._is_new:
302301
title = final_data.get(CONF_NAME, DEFAULT_NAME)
303-
if CONF_NAME in final_data:
304-
del final_data[CONF_NAME]
302+
final_data.pop(CONF_NAME, None)
305303
return self.async_create_entry(
306304
title=title,
307305
data=final_data,
@@ -313,10 +311,10 @@ async def async_step_advanced(
313311
)
314312

315313
# Build schema for advanced options based on selected model
316-
chat_model = self._temp_data.get(CONF_CHAT_MODEL, DEFAULT_CHAT_MODEL)
314+
chat_model = (self._temp_data or {}).get(CONF_CHAT_MODEL, DEFAULT_CHAT_MODEL)
317315
model_config = get_model_config(chat_model)
318316

319-
schema = {}
317+
schema: dict[Any, Any] = {}
320318

321319
# Add top_p if supported
322320
if model_config["supports_top_p"]:
@@ -437,9 +435,7 @@ def openai_config_option_schema(
437435
): SelectSelector(
438436
SelectSelectorConfig(
439437
options=[
440-
SelectOptionDict(
441-
value=strategy["key"], label=strategy["label"]
442-
)
438+
SelectOptionDict(value=strategy["key"], label=strategy["label"])
443439
for strategy in CONTEXT_TRUNCATE_STRATEGIES
444440
],
445441
mode=SelectSelectorMode.DROPDOWN,
@@ -552,12 +548,11 @@ async def async_step_advanced(
552548
"""Handle advanced options step."""
553549
if user_input is not None:
554550
# Merge advanced options with temp data
555-
final_data = {**self._temp_data, **user_input}
551+
final_data = {**(self._temp_data or {}), **user_input}
556552

557553
if self._is_new:
558554
title = final_data.get(CONF_NAME, DEFAULT_AI_TASK_NAME)
559-
if CONF_NAME in final_data:
560-
del final_data[CONF_NAME]
555+
final_data.pop(CONF_NAME, None)
561556
return self.async_create_entry(
562557
title=title,
563558
data=final_data,
@@ -569,10 +564,10 @@ async def async_step_advanced(
569564
)
570565

571566
# Build schema for advanced options based on selected model
572-
chat_model = self._temp_data.get(CONF_CHAT_MODEL, DEFAULT_CHAT_MODEL)
567+
chat_model = (self._temp_data or {}).get(CONF_CHAT_MODEL, DEFAULT_CHAT_MODEL)
573568
model_config = get_model_config(chat_model)
574569

575-
schema = {}
570+
schema: dict[Any, Any] = {}
576571

577572
# Add top_p if supported
578573
if model_config["supports_top_p"]:

0 commit comments

Comments
 (0)