Skip to content

Refactor: Enforce strict typed configuration and eradicate **kwargs tunnel (Resolves #481)#505

Merged
silverailscolo merged 1 commit intoramses-rf:masterfrom
PWhite-Eng:refactor/dto-and-strict-typing
Mar 8, 2026
Merged

Refactor: Enforce strict typed configuration and eradicate **kwargs tunnel (Resolves #481)#505
silverailscolo merged 1 commit intoramses-rf:masterfrom
PWhite-Eng:refactor/dto-and-strict-typing

Conversation

@PWhite-Eng
Copy link
Copy Markdown
Contributor

The Problem:

Initialization of the Gateway, Engine, and Transports relied heavily on unpacking dynamic **kwargs and tunneling data (such as Home Assistant's hass object) through opaque self._extra or hidden_kwargs dictionaries. This bypassed static type checking, hid the API contract from downstream consumers, and caused brittle integrations (Reference: Issue #481).

Consequences:

Consumers (like ramses_cc) could experience runtime crashes due to unvalidated configuration structures. Furthermore, static analysis tools like Mypy could not verify parameters, and the data flow to the transport layer (e.g., the Zigbee transport requiring the hass instance) was entirely undocumented and untyped.

The Fix:

Removed **kwargs and self._extra entirely from the instantiation chain. Introduced strongly typed dataclasses (GatewayConfig, TransportConfig, and DeviceTraits) to handle configuration, application context, and device instantiation explicitly.

Technical Implementation:

  • Created src/ramses_rf/models.py with a DeviceTraits DTO to enforce typed dictionary parsing for device instantiation.
  • Added app_context explicitly to GatewayConfig and TransportConfig. This allows passing the Home Assistant instance down to transports (like Zigbee) securely and transparently.
  • Refactored src/ramses_rf/gateway.py and src/ramses_tx/gateway.py signatures to completely drop **kwargs and hidden_kwargs.
  • Refactored transport_factory and ZigbeeTransport to pull hass directly from config.app_context instead of a generic extra dictionary.

Testing Performed:

  • Executed the full pytest suite locally to ensure no regressions in entity initialization, transport creation, or packet parsing. All tests pass.
  • Updated test_transport_zigbee.py to mock the new typed config structures.
  • Ran mypy in strict mode against the entire codebase to confirm zero static analysis errors across the new architectural boundaries.

Risks of NOT Implementing:

Leaving the codebase as-is means the public API remains undocumented and un-typeable. It preserves a "God-object" initialization anti-pattern that leaves downstream consumers highly vulnerable to hidden runtime crashes.

Risks of Implementing:

This introduces a breaking change for downstream consumers initializing the Gateway with legacy **kwargs. Downstream systems (ramses_cc) MUST update their initialization calls to use the new typed configuration classes.

Mitigation Steps:

Created clear, strictly-typed DTOs and configuration classes so the migration path for ramses_cc is obvious and IDE-autocomplete friendly. For the internal device layer, Device.create_from_schema temporarily utilizes a .to_dict() bridge from the new DTO to prevent a massive blast radius across all internal device subclasses.

AI Assistance Disclosure:

This contribution was developed with the assistance of Google Gemini 3.1 Pro for code generation and documentation. No Agentic AI systems were employed; all logic and implementations were reviewed, verified, and manually committed by the author.

@PWhite-Eng
Copy link
Copy Markdown
Contributor Author

Hi @IMMRMKW,

First off, great work on the Zigbee transport integration in #502! It is a brilliant addition to the project.

I wanted to give you a quick heads-up about this PR. Over the last few weeks, we've been heavily refactoring the underlying architecture of ramses_rf to enforce strict Python typing (Mypy) and establish a stable, explicitly documented public API (Issue #481).

As part of this cleanup, this PR completely removes the old **kwargs and self._extra dictionary tunnels from the Gateway and Engine initialization. Because the Zigbee transport was using _hass passed through that **kwargs tunnel, I have updated the Zigbee transport initialization to align with the new typed API.

What this means for ramses_cc: hass is no longer passed as a hidden kwarg. Instead, it is passed explicitly via the new typed configuration objects. ramses_cc will now need to initialize the Gateway something like this:

Python

from ramses_rf.gateway import GatewayConfig

config = GatewayConfig(
    app_context=hass,  # <-- hass gets explicitly passed here now
    disable_discovery=False,
    # ... other config options
)
gateway = Gateway(port_name, config=config, ...)

I know you have ongoing/WIP integrations for ramses_cc to support the ESP boards, so I apologize for the breaking change to the initialization signature. Let me know if you run into any friction adapting ramses_cc to use GatewayConfig, and I’d be more than happy to help you update the ramses_cc client creation logic.

As this is a breaking change, @silverailscolo is going to have to manage the version bump on both ramses_rf and ramses_cc to make sure this doesn't cause issues for everyone using the integration. Hopefully, he can give us guidance on a timeline for the version bump and what is included when.

Upcoming Refactoring: I still have a few things left that I want to refactor in ramses_rf. As part of standardizing the project's async handling, my next PR will likely include a few minor structural tweaks to the new Zigbee code. Specifically:

  1. Adding task tracking for background loops (like _send_unacked) so they can be safely awaited/cancelled during teardown.
  2. Implementing a Time-To-Live (TTL) cleanup for self._chunk_buffers to prevent memory leaks if fragmented payloads are dropped.
  3. Tightening up some of the generic except Exception: blocks into specific error traps.

Please take this in a positive way, as it is meant to be! I don't like to just moan in the comments; I prefer to get in and write code to help out. If there is anything in my upcoming PRs that you think I have got wrong or that causes issues for your Zigbee implementation, please let me know and I will be happy to change it. My only aim is to help build a robust foundation that reports errors cleanly.

Thanks again for the great feature!

Phil / PWhite-Eng

… DTOs" -m "Introduce GatewayConfig, TransportConfig, and DeviceTraits models. Remove opaque **kwargs, hidden_kwargs, and self._extra data tunnels across the Gateway and Transport layers. Update Zigbee transport to consume app_context explicitly.
@PWhite-Eng PWhite-Eng force-pushed the refactor/dto-and-strict-typing branch from 35a4fc5 to 17146ab Compare March 8, 2026 11:32
@github-actions
Copy link
Copy Markdown

github-actions bot commented Mar 8, 2026

Code Coverage

Package Line Rate Health
ramses_cli 91%
ramses_rf 81%
ramses_rf.device 75%
ramses_rf.system 78%
ramses_tx 72%
ramses_tx.protocol 81%
ramses_tx.transport 73%
test_ha_mqtt 95%
tests 94%
tests_cli 99%
tests_rf 92%
tests_rf.device 98%
tests_rf.virtual_rf 83%
tests_tx 98%
Summary 82% (13930 / 17079)

Minimum allowed line rate is 80%

@silverailscolo
Copy link
Copy Markdown
Collaborator

silverailscolo commented Mar 8, 2026

As this is a breaking change, @silverailscolo is going to have to manage the version bump on both ramses_rf and ramses_cc

@IMMRMKW @PWhite-Eng I suggest as follows:

ramses_rf

  • Merge PR 505
  • Merge PR 506 - 508
  • ... (unrelated/fixes)
  • Merge PR Bump version #503 to 0.55.4 (me)

  • Pre-release _rf 0.55.4, publish on pypi

ramses_cc

(Easy path would be to merge PR 515 and add fixes later, but that would leave us with an unstable integration, not preferred)


  • Pre-release _cc 0.55.4

@silverailscolo silverailscolo merged commit c79062c into ramses-rf:master Mar 8, 2026
6 checks passed
@silverailscolo silverailscolo added this to the 0.55.4 milestone Mar 8, 2026
@PWhite-Eng PWhite-Eng deleted the refactor/dto-and-strict-typing branch March 9, 2026 17:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants