Source code for nwp500.factory

"""Factory functions for convenient client creation and initialization.

This module provides helper functions to simplify the process of creating
and authenticating all Navien clients with a single function call.

Use factory functions when you want:
- Simplified initialization of all clients at once
- Automatic error handling during authentication
- Clear initialization order and dependencies
- Convenience over fine-grained control

Example:
    >>> auth, api, mqtt = await create_navien_clients(
    ...     email="user@example.com",
    ...     password="password"
    ... )
    >>> async with auth:
    ...     devices = await api.list_devices()
"""

from __future__ import annotations

import asyncio

from .api_client import NavienAPIClient
from .auth import NavienAuthClient
from .mqtt import NavienMqttClient

__all__ = ["create_navien_clients"]


[docs] async def create_navien_clients( email: str, password: str, ) -> tuple[NavienAuthClient, NavienAPIClient, NavienMqttClient]: """Create and authenticate all Navien clients with one call. This factory function handles the complete initialization sequence: 1. Creates an auth client with the provided credentials 2. Authenticates with the Navien API (via context manager) 3. Creates API and MQTT clients using the authenticated session 4. Returns all clients ready to use Args: email: Navien account email address password: Navien account password Returns: Tuple of (auth_client, api_client, mqtt_client) ready to use Raises: AuthenticationError: If authentication fails InvalidCredentialsError: If email/password are incorrect Example: >>> auth, api, mqtt = await create_navien_clients( ... email="user@example.com", ... password="password" ... ) >>> async with auth: ... # All clients are ready to use ... devices = await api.list_devices() ... await mqtt.connect() ... # Use clients ... Note: You must still use the auth client as a context manager to ensure the session is properly cleaned up: >>> auth, api, mqtt = await create_navien_clients(email, password) >>> async with auth: ... # Use api and mqtt clients here ... ... >>> # Session is automatically closed when exiting the context """ # Create auth client (doesn't authenticate yet) auth_client = NavienAuthClient(email, password) # Authenticate and enter context manager try: await auth_client.__aenter__() except asyncio.CancelledError: # Shield cleanup from further cancellation await asyncio.shield(auth_client.__aexit__(None, None, None)) raise except Exception as exc: await auth_client.__aexit__(type(exc), exc, exc.__traceback__) raise # Create API and MQTT clients that share the session try: api_client = NavienAPIClient(auth_client=auth_client) mqtt_client = NavienMqttClient(auth_client=auth_client) except Exception as exc: await auth_client.__aexit__(type(exc), exc, exc.__traceback__) raise return auth_client, api_client, mqtt_client