Coverage for src/lexigram/admin/multitenancy/models.py: 80%
20 statements
« prev ^ index » next coverage.py v7.15.4, created at 2026-08-24 23:39 +0800
« prev ^ index » next coverage.py v7.15.4, created at 2026-08-24 23:39 +0800
1"""Tenant data models — TenantConfig and TenantNotFoundError."""
3from __future__ import annotations
5from dataclasses import dataclass, field
6from typing import Any
9@dataclass
10class TenantConfig:
11 """Configuration for a single tenant.
13 Attributes:
14 tenant_id: Unique slug identifier (e.g. ``"acme"``).
15 name: Human-readable display name.
16 domain: Optional custom domain for subdomain-based resolution.
17 logo_url: Optional logo URL shown in the admin UI switcher.
18 primary_color: Optional hex colour override for the admin theme.
19 active: Whether this tenant is currently active.
20 metadata: Arbitrary extra metadata.
21 """
23 tenant_id: str
24 name: str
25 domain: str = ""
26 logo_url: str = ""
27 primary_color: str = ""
28 active: bool = True
29 metadata: dict[str, Any] = field(default_factory=dict)
31 def __post_init__(self) -> None:
32 if not self.tenant_id:
33 raise ValueError("TenantConfig.tenant_id must not be empty")
34 if not self.name:
35 raise ValueError("TenantConfig.name must not be empty")
38class TenantNotFoundError(KeyError):
39 """Raised when a tenant is not found in the registry."""
41 _code: str = "LEX_ERR_ADMIN_030"
44__all__ = [
45 "TenantConfig",
46 "TenantNotFoundError",
47]