Coverage for formkit_ninja / management / commands / generate_code.py: 0.00%

60 statements  

« prev     ^ index     » next       coverage.py v7.13.1, created at 2026-02-27 04:15 +0000

1""" 

2Django management command to generate code from FormKit schemas. 

3 

4This command reads FormKit schemas from the database and generates Django models, 

5Pydantic schemas, admin classes, and API endpoints. 

6""" 

7 

8from pathlib import Path 

9 

10from django.core.management.base import BaseCommand, CommandError 

11 

12from formkit_ninja import formkit_schema, models 

13from formkit_ninja.parser.formatter import CodeFormatter 

14from formkit_ninja.parser.generator import CodeGenerator 

15from formkit_ninja.parser.generator_config import GeneratorConfig 

16from formkit_ninja.parser.template_loader import DefaultTemplateLoader 

17 

18 

19class Command(BaseCommand): 

20 """Management command to generate code from FormKit schemas.""" 

21 

22 help = "Generate Django models, schemas, admin, and API code from FormKit schemas" 

23 

24 def add_arguments(self, parser): 

25 """Add command-line arguments.""" 

26 parser.add_argument( 

27 "--app-name", 

28 type=str, 

29 required=True, 

30 help="Name of the Django app (required)", 

31 ) 

32 parser.add_argument( 

33 "--output-dir", 

34 type=str, 

35 required=True, 

36 help="Directory where generated code will be written (required)", 

37 ) 

38 parser.add_argument( 

39 "--schema-label", 

40 type=str, 

41 default=None, 

42 help="Label of the schema to generate code for (optional, generates for all if not specified)", 

43 ) 

44 

45 def handle(self, *args, **options): 

46 """Execute the command.""" 

47 app_name = options["app_name"] 

48 output_dir_str = options["output_dir"] 

49 schema_label = options.get("schema_label") 

50 

51 # Validate and convert output directory 

52 try: 

53 output_dir = Path(output_dir_str) 

54 except Exception as e: 

55 raise CommandError(f"Invalid output directory: {e}") from e 

56 

57 # Validate output directory exists (or can be created) 

58 if not output_dir.exists(): 

59 try: 

60 output_dir.mkdir(parents=True, exist_ok=True) 

61 self.stdout.write( 

62 self.style.SUCCESS(f"Created output directory: {output_dir}"), 

63 ) 

64 except OSError as e: 

65 raise CommandError( 

66 f"Cannot create output directory {output_dir}: {e}", 

67 ) from e 

68 elif not output_dir.is_dir(): 

69 raise CommandError(f"Output path exists but is not a directory: {output_dir}") 

70 

71 # Query schemas from database 

72 if schema_label: 

73 schemas = models.FormKitSchema.objects.filter(label=schema_label) 

74 if not schemas.exists(): 

75 raise CommandError(f"Schema with label '{schema_label}' not found") 

76 else: 

77 schemas = models.FormKitSchema.objects.all() 

78 if not schemas.exists(): 

79 raise CommandError("No schemas found in database") 

80 

81 template_loader = DefaultTemplateLoader() 

82 formatter = CodeFormatter() 

83 

84 # Generate code for each schema 

85 success_count = 0 

86 error_count = 0 

87 

88 for schema in schemas: 

89 try: 

90 schema_name = schema.label or str(schema.id) 

91 self.stdout.write(f"Generating code for schema: {schema_name}") 

92 

93 # Initialize generator components with schema-specific config 

94 config = GeneratorConfig( 

95 app_name=app_name, 

96 output_dir=output_dir, 

97 schema_name=schema_name, 

98 ) 

99 generator = CodeGenerator( 

100 config=config, 

101 template_loader=template_loader, 

102 formatter=formatter, 

103 ) 

104 

105 # Convert schema to Pydantic format (with recursive=True to include children) 

106 # Note: to_pydantic() doesn't support recursive parameter, so we need to 

107 # call get_schema_values directly with recursive=True 

108 values = list(schema.get_schema_values(recursive=True)) 

109 pydantic_schema = formkit_schema.FormKitSchema.parse_obj(values) 

110 

111 # Generate code 

112 generator.generate(pydantic_schema) 

113 

114 self.stdout.write( 

115 self.style.SUCCESS( 

116 f"Successfully generated code for schema: {schema.label or schema.id}", 

117 ), 

118 ) 

119 success_count += 1 

120 except Exception as e: 

121 error_count += 1 

122 self.stdout.write( 

123 self.style.ERROR( 

124 f"Error generating code for schema {schema.label or schema.id}: {e}", 

125 ), 

126 ) 

127 

128 # Summary 

129 if success_count > 0: 

130 self.stdout.write( 

131 self.style.SUCCESS( 

132 f"\nSuccessfully generated code for {success_count} schema(s)", 

133 ), 

134 ) 

135 if error_count > 0: 

136 self.stdout.write( 

137 self.style.WARNING( 

138 f"\nFailed to generate code for {error_count} schema(s)", 

139 ), 

140 ) 

141 

142 if error_count > 0 and success_count == 0: 

143 raise CommandError("Code generation failed for all schemas")