Coverage for src / lexigram / admin / cli / generators / admin_action.py: 0%

27 statements  

« prev     ^ index     » next       coverage.py v7.13.5, created at 2026-08-11 02:25 +0800

1"""Admin action generator for creating custom admin UI actions.""" 

2 

3from __future__ import annotations 

4 

5from pathlib import Path 

6from typing import Any 

7 

8from lexigram.codegen.base import GenerationResult, GeneratorBase 

9 

10 

11class AdminActionGenerator(GeneratorBase): 

12 """Generator for creating custom admin UI actions.""" 

13 

14 name = "admin_action" 

15 description = "Generate a custom admin action" 

16 default_output_dir = "src/admin/actions" 

17 

18 def __init__(self, output_dir: str = "src/admin/actions") -> None: 

19 super().__init__( 

20 output_dir=output_dir, 

21 template_root=Path(__file__).parent.parent / "templates", 

22 ) 

23 

24 def generate( 

25 self, 

26 name: str, 

27 **options: Any, 

28 ) -> GenerationResult: 

29 """Generate an admin action.""" 

30 action_type = options.get("type", "row") 

31 target = options.get("target", "dialog") 

32 dry_run = bool(options.get("dry_run", False)) 

33 force = bool(options.get("force", False)) 

34 

35 action_name = name.capitalize() 

36 action_filename = f"{self._to_snake_case(name)}_action.py" 

37 file_path = self.output_dir / action_filename 

38 

39 if file_path.exists() and not force: 

40 return GenerationResult(files_skipped=[file_path]) 

41 

42 context = { 

43 "action_name": action_name, 

44 "action_name_snake": self._to_snake_case(name), 

45 "package_name": self._get_package_name(self.output_dir), 

46 "action_type": action_type, 

47 "target": target, 

48 } 

49 

50 content = self.render_template("admin_action.py.jinja2", context) 

51 

52 if dry_run: 

53 return GenerationResult(files_created=[file_path]) 

54 

55 self.output_dir.mkdir(parents=True, exist_ok=True) 

56 file_path.write_text(content) 

57 

58 return GenerationResult(files_created=[file_path])