Skip to content
Closed
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
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
# Changelog

## v1.14.3-1

- Correct typing of select_schedule

## v1.14.3

- Change representation of no-thermostat-schedule-defined to a single `off` option via PR [#899](https://github.com/plugwise/python-plugwise/pull/899)
Expand Down
2 changes: 1 addition & 1 deletion plugwise/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -584,7 +584,7 @@ class GwEntityData(TypedDict, total=False):
preset_modes: list[str] | None
# Schedules:
available_schedules: list[str]
select_schedule: str | None
select_schedule: str

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🗄️ Data Integrity & Integration | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== files =="
git ls-files | rg '(^|/)constants\.py$|fixtures/m_adam_multiple_devices_per_zone/data\.json$|TypedDict|GwEntityData' || true

echo "== constants snippet =="
sed -n '560,600p' plugwise/constants.py 2>/dev/null || true

echo "== fixture select_schedule occurrences =="
python3 - <<'PY'
import json
from pathlib import Path
p = Path('fixtures/m_adam_multiple_devices_per_zone/data.json')
if p.exists():
    data = json.loads(p.read_text())
    for k,v in data.items():
        if isinstance(v, dict):
            for kk, vv in v.items():
                if kk == 'select_schedule':
                    print(k, kk, type(vv).__name__, repr(vv)[:240])
else:
    print('fixture missing')
PY

echo "== GwEntityData usages =="
rg -n "class GwEntityData|GwEntityData\(|select_schedule" plugwise fixtures -S || true

Repository: plugwise/python-plugwise

Length of output: 7254


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== GwEntityData definition and surrounding helpers =="
sed -n '440,595p' plugwise/constants.py

echo "== data.py select_schedule construction context =="
sed -n '250,295p' plugwise/data.py

echo "== smile.py select_schedule parser context =="
sed -n '225,265p' plugwise/smile.py

echo "== fixture Garage entity context =="
python3 - <<'PY'
import json
from pathlib import Path
p = Path('fixtures/m_adam_multiple_devices_per_zone/data.json')
data = json.loads(p.read_text())
for cid, entity in data.items():
    if entity.get('device_name') == 'Garage':
        print(json.dumps(entity, indent=2, ensure_ascii=False)[:2500])
        break
PY

echo "== static shape check for presence of select_schedule keys =="
python3 - <<'PY'
import json
from pathlib import Path

for path in sorted(Path('fixtures').rglob('data.json')):
    data = json.loads(path.read_text())
    for cid, entity in data.items():
        if isinstance(entity, dict) and 'select_schedule' in entity:
            val = entity['select_schedule']
            if val is None and str(entity.get('device_name')) != 'Garage':
                other = {k: entity.get(k) for k in ('device_name', 'device_type', 'firmware_version')}
                print(f'{path}:{cid}: device={repr(other)} select_schedule=None')
PY

Repository: plugwise/python-plugwise

Length of output: 8069


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== constants.py full GwEntityData excerpt =="
sed -n '530,610p' plugwise/constants.py

echo "== data.py construction excerpt around GwEntityData creation =="
sed -n '1,130p' plugwise/data.py
echo "---"
sed -n '260,350p' plugwise/data.py

echo "== all exact GwEntityData calls and TypedDict imports =="
rg -n "^from typing import .*TypedDict|TypedDict|GwEntityData\(" plugwise -S || true

echo "== fixture entity body for select_schedule null entity =="
python3 - <<'PY'
import json
from pathlib import Path
p = Path('fixtures/m_adam_multiple_devices_per_zone/data.json')
data = json.loads(p.read_text())
target = '446ac08dd04d4eff8ac57489757b7314'
print(json.dumps({target: data[target]}, indent=2, ensure_ascii=False))
PY

Repository: plugwise/python-plugwise

Length of output: 11041


Keep select_schedule aligned with the Garage fixture.

GwEntityData and _climate_data() require a selected schedule during zone data construction, but fixtures/m_adam_multiple_devices_per_zone/data.json stores "select_schedule": null for the Garage thermostat. If this fixture represents valid gateway data, preserve str | None or normalize null before using this value.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@plugwise/constants.py` at line 587, Update the select_schedule field in
GwEntityData and the _climate_data() construction path to support the Garage
fixture’s null value, either by typing it as str | None or normalizing null
before use; preserve existing behavior for non-null schedules.


climate_mode: str
# Extra for Adam Master Thermostats
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"

[project]
name = "plugwise"
version = "1.14.3"
version = "1.14.3-1"
license = "MIT"
description = "Plugwise Smile (Adam/Anna/P1) and Stretch module for Python 3."
readme = "README.md"
Expand Down
Loading