Coverage for src/lexigram/admin/schema/boolean.py: 93%

46 statements  

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

1from __future__ import annotations 

2 

3from dataclasses import dataclass 

4from typing import Any 

5 

6from lexigram.admin.schema.base import SchemaField 

7from lexigram.admin.schema.exceptions import FieldError 

8from lexigram.result import Err, Ok, Result 

9from lexigram.ui import Element, Switch 

10 

11 

12@dataclass(frozen=True, kw_only=True) 

13class BooleanField(SchemaField[bool]): 

14 """A boolean toggle field rendered as a Switch.""" 

15 

16 def render_infolist_entry(self, value: Any) -> Any: 

17 from lexigram.ui import InfolistEntry, InfolistEntryType 

18 

19 return InfolistEntry( 

20 name=self.name, 

21 label=self.label or self.name.replace("_", " ").title(), 

22 value=value, 

23 type=InfolistEntryType.BOOLEAN, 

24 ) 

25 

26 def render_form( 

27 self, value: bool | None, *, errors: list[str] | None = None 

28 ) -> Element: 

29 kwargs: dict[str, Any] = { 

30 "name": self.name, 

31 "value": value if value is not None else False, 

32 } 

33 if self.label is not None: 

34 kwargs["label"] = self.label 

35 else: 

36 kwargs["label"] = "" 

37 if errors: 

38 kwargs["error"] = errors[0] 

39 if self.readonly: 

40 kwargs["disabled"] = True 

41 return Switch(**kwargs).render() 

42 

43 def render_column(self, record: Any, value: bool | None) -> Element: 

44 if value is None: 

45 return Element("span", "\u2014", class_="text-muted") 

46 if value: 

47 return Element("span", "\u2713", class_="text-success") 

48 return Element("span", "\u2717", class_="text-destructive") 

49 

50 def from_form(self, raw: str | None) -> Result[bool | None, FieldError]: 

51 if raw is None: 

52 return Ok(None) 

53 stripped = raw.strip() 

54 if not stripped: 

55 if self.nullable: 

56 return Ok(None) 

57 return Err(FieldError("Must be true or false")) 

58 lower = stripped.lower() 

59 if lower in ("true", "1", "yes"): 

60 return Ok(True) 

61 if lower in ("false", "0", "no"): 

62 return Ok(False) 

63 return Err(FieldError("Must be true or false")) 

64 

65 def to_form(self, value: bool | None) -> str: 

66 if value is None: 

67 return "" 

68 return "true" if value else "false"