Coverage for formkit_ninja / management / commands / generate_code.py: 0.00%
60 statements
« prev ^ index » next coverage.py v7.13.1, created at 2026-03-06 04:12 +0000
« prev ^ index » next coverage.py v7.13.1, created at 2026-03-06 04:12 +0000
1"""
2Django management command to generate code from FormKit schemas.
4This command reads FormKit schemas from the database and generates Django models,
5Pydantic schemas, admin classes, and API endpoints.
6"""
8from pathlib import Path
10from django.core.management.base import BaseCommand, CommandError
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
19class Command(BaseCommand):
20 """Management command to generate code from FormKit schemas."""
22 help = "Generate Django models, schemas, admin, and API code from FormKit schemas"
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 )
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")
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
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}")
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")
81 template_loader = DefaultTemplateLoader()
82 formatter = CodeFormatter()
84 # Generate code for each schema
85 success_count = 0
86 error_count = 0
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}")
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 )
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)
111 # Generate code
112 generator.generate(pydantic_schema)
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 )
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 )
142 if error_count > 0 and success_count == 0:
143 raise CommandError("Code generation failed for all schemas")