Coverage for src/lexigram/admin/multitenancy/models.py: 100%

20 statements  

« prev     ^ index     » next       coverage.py v7.15.4, created at 2026-08-21 14:56 +0800

1"""Tenant data models — TenantConfig and TenantNotFoundError.""" 

2 

3from __future__ import annotations 

4 

5from dataclasses import dataclass, field 

6from typing import Any 

7 

8 

9@dataclass 

10class TenantConfig: 

11 """Configuration for a single tenant. 

12 

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 """ 

22 

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) 

30 

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") 

36 

37 

38class TenantNotFoundError(KeyError): 

39 """Raised when a tenant is not found in the registry.""" 

40 

41 _code: str = "LEX_ERR_ADMIN_030" 

42 

43 

44__all__ = [ 

45 "TenantConfig", 

46 "TenantNotFoundError", 

47]