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

41 statements  

« prev     ^ index     » next       coverage.py v7.13.5, created at 2026-08-13 22:14 +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_form( 

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

18 ) -> Element: 

19 kwargs: dict[str, Any] = { 

20 "name": self.name, 

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

22 } 

23 if self.label is not None: 

24 kwargs["label"] = self.label 

25 else: 

26 kwargs["label"] = "" 

27 if errors: 

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

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

30 

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

32 if value is None: 

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

34 if value: 

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

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

37 

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

39 if raw is None: 

40 return Ok(None) 

41 stripped = raw.strip() 

42 if not stripped: 

43 if self.nullable: 

44 return Ok(None) 

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

46 lower = stripped.lower() 

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

48 return Ok(True) 

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

50 return Ok(False) 

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

52 

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

54 if value is None: 

55 return "" 

56 return "true" if value else "false"