Skip to content

feat(akuvox, schlage): converge legacy tag format to canonical lcm:<slot>: - #1242

Merged
raman325 merged 1 commit into
mainfrom
feat/akuvox-schlage-tag-migration
Jun 10, 2026
Merged

feat(akuvox, schlage): converge legacy tag format to canonical lcm:<slot>:#1242
raman325 merged 1 commit into
mainfrom
feat/akuvox-schlage-tag-migration

Conversation

@raman325

Copy link
Copy Markdown
Owner

Proposed change

Final piece of the user-tag idempotency rollout. Akuvox and Schlage have used a slot-encoding tag ([LCM:<slot>] <friendly name>) since they identify codes by name rather than slot — same purpose, same mechanism, different format from what Matter and Z-Wave now use. This PR converges them on the canonical lcm:<slot>:<friendly name> format introduced in #1239, so every provider that needs a name-side tag uses the same convention.

How it works

A single import swap per provider: the local _make_tagged_name alias now points at the canonical builder (make_tagged_name) instead of the deprecated legacy builder (make_legacy_tagged_name). Every existing call site that writes a tagged name now emits canonical format; no other code changes needed.

Migration

Migration is implicit and per-code/per-user, not a one-shot sweep:

  1. _parse_tag already accepts both formats (the tolerant parser landed in refactor(providers/_util): tolerant tag parser + new compact format builder #1238), so legacy-tagged codes are still discovered correctly by slot.
  2. On the next write that touches a code/user (set, replace, name change), the provider's async_set_credential recomputes the tagged name via _make_tagged_name (now canonical) and rewrites the lock-stored name.
  3. The friendly portion is preserved verbatim.

For a code LCM never touches after the upgrade, the legacy tag stays — and continues to work because the parser accepts it. The format converges as installs see normal LCM activity.

Regression coverage

  • Schlage test_set_credential_migrates_legacy_format_tag_on_write — seeds a [LCM:1] Guest code, asserts the post-write code is named lcm:1:Guest and the legacy entry is cleaned up.
  • Akuvox same shape — the modify_user call carries the canonical name.

Existing tests were swept: per-provider fixture seeds were converted from legacy to canonical format (representing the post-migration steady state). The parse_tag parametrize tests intentionally keep the legacy strings so the tolerant parser's back-compat behavior stays pinned; if the legacy branch is ever removed from _util.py, those tests will catch it.

Type of change

  • Dependency upgrade
  • Bugfix (non-breaking change which fixes an issue)
  • New feature (which adds functionality)
  • Breaking change (fix/feature causing existing functionality to break)
  • Code quality improvements to existing code or addition of tests

Additional information

Test plan

  • Full suite passes locally (1151/1151)
  • Live Akuvox lock — set a PIN on a slot that previously had a [LCM:<slot>] tagged user; verify the user's name is rewritten to lcm:<slot>: form after the write
  • Live Schlage lock — same as above for a Schlage code
  • Live Akuvox/Schlage lock — verify codes never re-touched by LCM after upgrade still register as occupied (legacy parser still works)

🤖 Generated with Claude Code

…lot>:

PR C2 -- final piece of the user-tag idempotency rollout. Akuvox and
Schlage have used a slot-encoding tag (``[LCM:<slot>] <friendly
name>``) since they identify codes by name rather than slot. Converge
on the canonical ``lcm:<slot>:<friendly name>`` format introduced for
Matter (#1239) so the codebase has one convention across every
provider that needs a name-side tag.

Implementation is a single import swap per provider: the local
``_make_tagged_name`` alias now points at the canonical builder
(``make_tagged_name``) instead of the deprecated legacy builder
(``make_legacy_tagged_name``). Every existing call site that writes
a tagged name now emits canonical format; no other code changes
needed.

Migration is implicit: ``_parse_tag`` already accepts both formats
(tolerant parser added in #1238), so legacy-tagged users are still
discovered by slot. On the next write that touches a code/user, the
provider's ``async_set_credential`` recomputes the tagged name via
``_make_tagged_name`` (now canonical) and rewrites the lock-stored
name. The friendly portion is preserved verbatim.

Regression tests added:
* Schlage: ``test_set_credential_migrates_legacy_format_tag_on_write``
  -- seeds a ``[LCM:1] Guest`` code, asserts the post-write code is
  named ``lcm:1:Guest`` and that the legacy entry is cleaned up.
* Akuvox: same shape; the modify_user call carries canonical name.

Existing tests sweep: per-provider fixture seeds were converted from
legacy to canonical format (representing the post-migration steady
state). The ``parse_tag`` parametrize tests intentionally keep the
legacy strings to lock in the tolerant parser's back-compat
behavior; the legacy builder is no longer referenced anywhere.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Entire-Checkpoint: 2a0cca3bc821
Copilot AI review requested due to automatic review settings June 10, 2026 21:01
@github-actions github-actions Bot added python Pull requests that update Python code enhancement New feature or request labels Jun 10, 2026
@raman325
raman325 merged commit a24c297 into main Jun 10, 2026
14 checks passed
@raman325
raman325 deleted the feat/akuvox-schlage-tag-migration branch June 10, 2026 21:02
@codecov

codecov Bot commented Jun 10, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 96.98%. Comparing base (f12bb47) to head (4a3de41).
⚠️ Report is 3 commits behind head on main.
✅ All tests successful. No failed tests found.

Additional details and impacted files

Impacted file tree graph

@@           Coverage Diff           @@
##             main    #1242   +/-   ##
=======================================
  Coverage   96.97%   96.98%           
=======================================
  Files          53       53           
  Lines        6153     6168   +15     
  Branches      461      461           
=======================================
+ Hits         5967     5982   +15     
  Misses        186      186           
Flag Coverage Δ
python 97.52% <100.00%> (+<0.01%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

Files with missing lines Coverage Δ
...m_components/lock_code_manager/providers/akuvox.py 95.70% <100.00%> (ø)
..._components/lock_code_manager/providers/schlage.py 96.29% <100.00%> (ø)

... and 1 file with indirect coverage changes

🚀 New features to boost your workflow:
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Copilot AI left a comment

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.

Pull request overview

This PR completes the Akuvox/Schlage portion of the user-tag idempotency rollout by switching those providers from emitting the legacy bracketed tag format ([LCM:<slot>] <name>) to the canonical tag format (lcm:<slot>:<name>), aligning them with other providers and the shared tolerant parser in providers/_util.py.

Changes:

  • Switch Akuvox and Schlage providers to build tagged names using the canonical make_tagged_name() helper.
  • Update provider and E2E tests to expect canonical tag strings by default.
  • Add regression tests that confirm a legacy-tagged code/user is rewritten to canonical format on the next write.

Reviewed changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
custom_components/lock_code_manager/providers/schlage.py Swap to canonical tag builder for all Schlage name writes.
custom_components/lock_code_manager/providers/akuvox.py Swap to canonical tag builder for all Akuvox name writes.
tests/providers/schlage/test_provider.py Update expectations to canonical tags; add legacy→canonical migration-on-write test.
tests/providers/schlage/test_e2e.py Update E2E assertions to canonical tags.
tests/providers/akuvox/test_provider.py Update expectations to canonical tags; add/adjust migration and set-credential tests.
tests/providers/akuvox/test_e2e.py Update E2E assertions to canonical tags.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines 36 to 38
from ._base import BaseLock
from ._util import make_legacy_tagged_name as _make_tagged_name, parse_tag as _parse_tag
from ._util import make_tagged_name as _make_tagged_name, parse_tag as _parse_tag
from .const import LOGGER
Comment on lines 29 to 32
from ..domain.models import SlotCredential
from ._base import BaseLock
from ._util import make_legacy_tagged_name as _make_tagged_name, parse_tag as _parse_tag
from ._util import make_tagged_name as _make_tagged_name, parse_tag as _parse_tag
from .const import LOGGER

assert result is True
assert modify_calls[0]["name"] == "[LCM:1] Guest"
# Friendly portion preserved verbatim; only the format changed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request python Pull requests that update Python code

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants