Coverage for src/lexigram/graphql/cli/generators/dataloader.py: 72%

25 statements  

« prev     ^ index     » next       coverage.py v7.15.4, created at 2026-08-25 04:37 +0800

1"""DataLoaderProtocol Generator for Lexigram CLI. 

2 

3Generates DataLoaderProtocol classes for GraphQL to solve N+1 query problems. 

4""" 

5 

6from __future__ import annotations 

7 

8from pathlib import Path 

9from typing import Any 

10 

11import jinja2 

12 

13from lexigram.codegen.base import GenerationResult, GeneratorBase 

14 

15 

16class DataLoaderGenerator(GeneratorBase): 

17 """Generator for GraphQL DataLoaders. 

18 

19 Creates DataLoaderProtocol classes that batch and cache data fetches 

20 to efficiently resolve GraphQL queries. 

21 """ 

22 

23 name = "dataloader" 

24 description = "Generate a GraphQL DataLoaderProtocol to solve N+1 problems" 

25 default_output_dir = "src/graphql/dataloaders" 

26 

27 def __init__(self, output_dir: str = "src/graphql/dataloaders") -> None: 

28 template_dir = Path(__file__).parent.parent / "templates" 

29 super().__init__( 

30 output_dir=output_dir, 

31 template_root=template_dir, 

32 ) 

33 self._jinja_env = jinja2.Environment( 

34 loader=jinja2.FileSystemLoader(str(template_dir)), 

35 autoescape=True, 

36 ) 

37 

38 def get_name(self) -> str: 

39 return self.name 

40 

41 def get_description(self) -> str: 

42 return self.description 

43 

44 def generate( 

45 self, 

46 name: str, 

47 output_dir: str = "src/graphql/dataloaders", 

48 key_type: str = "str", 

49 **kwargs: Any, 

50 ) -> GenerationResult: 

51 """Generate a DataLoaderProtocol. 

52 

53 Args: 

54 name: Name of the DataLoaderProtocol (e.g., "UserLoader") 

55 output_dir: Directory to write the file 

56 key_type: Type of the key (e.g., "str", "int") 

57 

58 Returns: 

59 GeneratorResult with generated file path 

60 """ 

61 snake_name = self._to_snake_case(name) 

62 output_path = Path(output_dir) / f"{snake_name}.py" 

63 

64 template = self._jinja_env.get_template("dataloader.py.jinja2") 

65 rendered = template.render( 

66 name=name, 

67 snake_name=snake_name, 

68 key_type=key_type, 

69 ) 

70 

71 output_path.parent.mkdir(parents=True, exist_ok=True) 

72 output_path.write_text(rendered) 

73 

74 return GenerationResult(files_created=[output_path])