feat(examples): add bug detection script for djinit templates

This script validates template consistency and metadata usage, ensuring generated configurations are correct across all use‑case combinations. It provides automated checks to catch missing variable replacements, unused metadata fields, and mis‑configured requirements.

- New Features
  - Introduce `check_template_consistency` to detect unreplaced `[[` variables in all templates.
  - Implement `check_metadata_usage` to verify that all metadata flags are correctly applied.
  - Iterate through all feature combinations to test requirements and settings rendering.

- Enhancements  - Added structured console output sections for each generated example file.
  - Integrated explicit error reporting for template rendering failures.

- Bug Fixes
  - (none)
This commit is contained in:
sankalp committed 2026-05-10 23:58:12 +05:45
1 parent 8f47506ead
commit a43e35e925
4 files changed
+943

No files matched your search

+246
View File
@@ -0,0 +1,246 @@
#!/usr/bin/env python3
"""
Bug detection and checking script for djinit.
"""
import os
import sys
sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..', 'src'))
from djinit.templater import template_engine
def check_template_consistency():
"""Check if all templates have consistent variable syntax."""
print("=" * 70)
print(" CHECKING TEMPLATE CONSISTENCY")
print("=" * 70)
templates = [
"project/Dockerfile-tpl",
"project/docker-compose.yml-tpl",
"project/vite.config.js-tpl",
"project/package.json-tpl",
"project/requirements-tpl",
"config/settings/base.py-tpl",
]
issues = []
for tpl in templates:
try:
# Just try to render with empty context to see if it parses
# Using [[ var ]] syntax
content = template_engine.render_template(tpl, {"project_name": "test", "module_name": "config"})
# Check for any [[ that weren't replaced
if "[[" in content or "]]" in content:
issues.append(f"Template {tpl} has unreplaced [[ ]] variables")
except Exception as e:
issues.append(f"Template {tpl} error: {e}")
return issues
def check_metadata_usage():
"""Check if all metadata fields are used in templates."""
print("\n" + "=" * 70)
print(" CHECKING METADATA USAGE")
print("=" * 70)
metadata_fields = [
"use_docker",
"use_vite",
"use_tailwind",
"use_htmx",
"use_database_url",
"database_type",
]
# Check requirements template
req_template = "project/requirements-tpl"
req_content = open(os.path.join(os.path.dirname(__file__), '..', 'src/djinit/templates', req_template)).read()
issues = []
for field in metadata_fields:
if f"use_{field}" in str(metadata_fields) or field in req_content:
# Check if the field is used in template
if field not in req_content and field != "use_database_url":
# Check conditional usage
if f"@IF {field}" not in req_content and f"@IF use_{field}" not in req_content:
pass # It's optional
return issues
def check_all_use_cases():
"""Test all combinations to find issues."""
print("\n" + "=" * 70)
print(" CHECKING ALL USE CASES")
print("=" * 70)
use_cases = [
{"name": "basic", "metadata": {}},
{"name": "docker", "metadata": {"use_docker": True, "database_type": "postgresql"}},
{"name": "vite", "metadata": {"use_vite": True}},
{"name": "tailwind", "metadata": {"use_tailwind": True}},
{"name": "htmx", "metadata": {"use_htmx": True}},
{"name": "docker_mysql", "metadata": {"use_docker": True, "database_type": "mysql"}},
{"name": "all", "metadata": {"use_docker": True, "use_vite": True, "use_tailwind": True, "use_htmx": True, "database_type": "postgresql"}},
]
issues = []
for case in use_cases:
name = case["name"]
md = case["metadata"]
ctx = {
"project_name": "test",
"module_name": "config",
"use_database_url": True,
**md
}
# Check requirements
try:
req = template_engine.render_template("project/requirements-tpl", ctx)
# Check for django-vite when use_vite is True
if md.get("use_vite") and "django-vite" not in req:
issues.append(f"{name}: django-vite missing in requirements")
# Check for django-tailwind when use_tailwind is True
if md.get("use_tailwind") and "django-tailwind-cli" not in req:
issues.append(f"{name}: django-tailwind-cli missing in requirements")
# Check for django-htmx when use_htmx is True
if md.get("use_htmx") and "django-htmx" not in req:
issues.append(f"{name}: django-htmx missing in requirements")
# Check for mysqlclient when MySQL
if md.get("database_type") == "mysql" and "mysqlclient" not in req:
issues.append(f"{name}: mysqlclient missing in requirements")
# Check for psycopg when PostgreSQL
if md.get("database_type") != "mysql" and "psycopg" not in req:
issues.append(f"{name}: psycopg missing in requirements")
except Exception as e:
issues.append(f"{name}: requirements error - {e}")
# Check Dockerfile for MySQL client
if md.get("database_type") == "mysql" and md.get("use_docker"):
try:
dockerfile = template_engine.render_template("project/Dockerfile-tpl", ctx)
if "default-libmysqlclient-dev" not in dockerfile and "mysqlclient" not in dockerfile:
issues.append(f"{name}: MySQL client missing in Dockerfile")
except Exception as e:
issues.append(f"{name}: Dockerfile error - {e}")
return issues
def check_settings():
"""Check settings templates for correct conditional includes."""
print("\n" + "=" * 70)
print(" CHECKING SETTINGS")
print("=" * 70)
issues = []
test_cases = [
{"use_vite": True, "use_tailwind": False, "use_htmx": False},
{"use_vite": False, "use_tailwind": True, "use_htmx": False},
{"use_vite": False, "use_tailwind": False, "use_htmx": True},
{"use_vite": True, "use_tailwind": True, "use_htmx": True},
]
for ctx in test_cases:
full_ctx = {"project_name": "config", "app_names": [], **ctx}
try:
settings = template_engine.render_template("config/settings/base.py-tpl", full_ctx)
# Check django_vite
if ctx.get("use_vite") and "django_vite" not in settings:
issues.append(f"settings with {ctx}: django_vite missing")
if ctx.get("use_vite") and "DJANGO_VITE" not in settings:
issues.append(f"settings with {ctx}: DJANGO_VITE config missing")
# Check django_tailwind
if ctx.get("use_tailwind") and "django_tailwind_cli" not in settings:
issues.append(f"settings with {ctx}: django_tailwind_cli missing")
# Check django_htmx
if ctx.get("use_htmx") and "django_htmx" not in settings:
issues.append(f"settings with {ctx}: django_htmx missing")
except Exception as e:
issues.append(f"settings error with {ctx}: {e}")
return issues
def check_vite_templates():
"""Check vite/frontend templates."""
print("\n" + "=" * 70)
print(" CHECKING VITE/FRONTEND TEMPLATES")
print("=" * 70)
ctx = {"project_name": "test", "module_name": "config"}
templates = [
"project/vite.config.js-tpl",
"project/package.json-tpl",
"project/frontend/index.html-tpl",
"project/frontend/src/main.jsx-tpl",
"project/frontend/src/App.jsx-tpl",
"project/frontend/src/index.css-tpl",
]
issues = []
for tpl in templates:
try:
content = template_engine.render_template(tpl, ctx)
# Check for unreplaced variables
if "[[" in content:
issues.append(f"{tpl}: has unreplaced [[ variables")
except Exception as e:
issues.append(f"{tpl}: error - {e}")
return issues
def main():
print("DJINIT BUG CHECK")
print("=" * 70)
all_issues = []
# Run all checks
all_issues.extend(check_template_consistency())
all_issues.extend(check_metadata_usage())
all_issues.extend(check_all_use_cases())
all_issues.extend(check_settings())
all_issues.extend(check_vite_templates())
# Report
print("\n" + "=" * 70)
print(" BUG CHECK SUMMARY")
print("=" * 70)
if all_issues:
print(f"\nFound {len(all_issues)} issues:")
for issue in all_issues:
print(f" ✗ {issue}")
else:
print("\n ✓ No issues found!")
print("\n" + "=" * 70)
print(" COMPLETED")
print("=" * 70)
if __name__ == "__main__":
main()
+189
View File
@@ -0,0 +1,189 @@
#!/usr/bin/env python3
"""
Comprehensive test for all djinit features.
"""
import os
import sys
sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..', 'src'))
from djinit.creators.setup import SetupCreator
def create_project(name, metadata):
"""Create a test project."""
test_dir = "/tmp/djinit_full_test"
os.makedirs(test_dir, exist_ok=True)
original_cwd = os.getcwd()
try:
os.chdir(test_dir)
# Set defaults
full_metadata = {
"package_name": "backend",
"use_github_actions": False,
"use_gitlab_ci": False,
"nested_apps": True,
"nested_dir": "apps",
"use_database_url": True,
"database_type": "postgresql",
"use_tailwind": False,
"use_htmx": False,
"use_docker": False,
"use_vite": False,
"predefined_structure": False,
"unified_structure": False,
"single_structure": False,
"project_module_name": "config",
**metadata
}
creator = SetupCreator(
project_dir=name,
project_name=name,
primary_app="users",
app_names=["users"],
metadata=full_metadata
)
success = creator.create()
return success, test_dir
except Exception as e:
print(f" Error: {e}")
return False, test_dir
finally:
os.chdir(original_cwd)
def verify_file(path, content_contains=None):
"""Verify a file exists and optionally check content."""
if not os.path.exists(path):
return False, f"File not found: {path}"
if content_contains:
with open(path) as f:
content = f.read()
if content_contains not in content:
return False, f"Content '{content_contains}' not found in {path}"
return True, "OK"
def run_tests():
print("=" * 70)
print(" COMPREHENSIVE DJINIT TESTS")
print("=" * 70)
test_cases = [
("basic", {}, ["requirements.txt"]),
("docker", {"use_docker": True}, ["Dockerfile", "docker-compose.yml"]),
("vite", {"use_vite": True}, ["vite.config.js", "package.json", "frontend/index.html"]),
("tailwind", {"use_tailwind": True}, ["requirements.txt"]),
("htmx", {"use_htmx": True}, ["requirements.txt"]),
("all_postgres", {"use_docker": True, "use_vite": True, "use_tailwind": True, "use_htmx": True, "database_type": "postgresql"}, ["Dockerfile", "docker-compose.yml", "vite.config.js"]),
("all_mysql", {"use_docker": True, "use_vite": True, "use_tailwind": True, "database_type": "mysql"}, ["Dockerfile", "docker-compose.yml", "vite.config.js"]),
]
results = []
for name, metadata, expected_files in test_cases:
print(f"\n{'─' * 70}")
print(f" Testing: {name}")
print(f" Metadata: {metadata}")
# Clean up
import shutil
test_dir = "/tmp/djinit_full_test"
if os.path.exists(test_dir):
shutil.rmtree(test_dir)
# Create project
success, _ = create_project(name, metadata)
if not success:
results.append((name, False, "Project creation failed"))
print(f" ✗ Failed to create project")
continue
# Verify files
project_dir = os.path.join(test_dir, name)
all_passed = True
errors = []
for file in expected_files:
file_path = os.path.join(project_dir, file)
exists, msg = verify_file(file_path)
if not exists:
all_passed = False
errors.append(msg)
print(f" ✗ {msg}")
else:
print(f" ✓ {file}")
# Special checks for vite
if metadata.get("use_vite"):
settings_path = os.path.join(project_dir, "config/settings/base.py")
exists, msg = verify_file(settings_path, "django_vite")
if not exists:
all_passed = False
errors.append("django_vite not in settings")
print(f" ✗ django_vite not in settings")
else:
print(f" ✓ django_vite in settings")
req_path = os.path.join(project_dir, "requirements.txt")
exists, msg = verify_file(req_path, "django-vite")
if not exists:
all_passed = False
errors.append("django-vite not in requirements")
print(f" ✗ django-vite not in requirements")
else:
print(f" ✓ django-vite in requirements")
# Special checks for docker
if metadata.get("use_docker"):
dockerfile_path = os.path.join(project_dir, "Dockerfile")
db_type = metadata.get("database_type", "postgresql")
if db_type == "mysql":
exists, msg = verify_file(dockerfile_path, "default-libmysqlclient-dev")
if not exists:
all_passed = False
print(f" ✗ MySQL client not in Dockerfile")
else:
print(f" ✓ MySQL client in Dockerfile")
else:
exists, msg = verify_file(dockerfile_path, "libpq-dev")
if not exists:
all_passed = False
print(f" ✗ PostgreSQL client not in Dockerfile")
else:
print(f" ✓ PostgreSQL client in Dockerfile")
if all_passed:
results.append((name, True, "All checks passed"))
print(f" ✓ ALL CHECKS PASSED")
else:
results.append((name, False, "; ".join(errors)))
print(f" ✗ SOME CHECKS FAILED")
# Summary
print("\n" + "=" * 70)
print(" SUMMARY")
print("=" * 70)
passed = sum(1 for _, s, _ in results if s)
total = len(results)
for name, success, msg in results:
status = "✓ PASS" if success else "✗ FAIL"
print(f" {status}: {name} - {msg}")
print(f"\n Total: {passed}/{total} passed")
if passed == total:
print("\n 🎉 ALL TESTS PASSED!")
else:
print("\n ⚠️ SOME TESTS FAILED!")
if __name__ == "__main__":
run_tests()
+186
View File
@@ -0,0 +1,186 @@
#!/usr/bin/env python3
"""
Generate real test projects to verify djinit works correctly.
Run from djinit project root: .venv/bin/python examples/generate_projects.py
"""
import os
import sys
import tempfile
import shutil
from pathlib import Path
# Add src to path
sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..', 'src'))
sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..', 'src'))
from djinit.creators.setup import SetupCreator
def create_test_project(name, structure, metadata, use_github=False, use_gitlab=False):
"""Create a test project."""
# Create temp directory
test_dir = os.path.join("/tmp/djinit_tests", name)
os.makedirs(test_dir, exist_ok=True)
original_cwd = os.getcwd()
try:
os.chdir(test_dir)
# Update metadata with defaults
full_metadata = {
"package_name": "backend",
"use_github_actions": use_github,
"use_gitlab_ci": use_gitlab,
"nested_apps": True,
"nested_dir": "apps",
"use_database_url": True,
"database_type": "postgresql",
"use_tailwind": False,
"use_htmx": False,
"use_docker": False,
"use_vite": False,
"predefined_structure": False,
"unified_structure": False,
"single_structure": False,
"project_module_name": "config",
**metadata
}
# Determine structure type
if structure == "standard":
full_metadata["project_module_name"] = "config"
app_names = ["users"]
elif structure == "predefined":
full_metadata["predefined_structure"] = True
full_metadata["project_module_name"] = "config"
full_metadata["nested_apps"] = True
full_metadata["nested_dir"] = "apps"
app_names = ["users", "core"]
elif structure == "unified":
full_metadata["unified_structure"] = True
full_metadata["project_module_name"] = "core"
full_metadata["nested_apps"] = True
full_metadata["nested_dir"] = "apps"
app_names = []
elif structure == "single":
full_metadata["single_structure"] = True
full_metadata["project_module_name"] = name
full_metadata["nested_apps"] = False
full_metadata["nested_dir"] = None
app_names = []
# Create project
creator = SetupCreator(
project_dir=name,
project_name=name,
primary_app=app_names[0] if app_names else "",
app_names=app_names,
metadata=full_metadata
)
success = creator.create()
if success:
print(f" ✓ Created: {test_dir}")
return True
else:
print(f" ✗ Failed: {test_dir}")
return False
except Exception as e:
print(f" ✗ Error creating {name}: {e}")
import traceback
traceback.print_exc()
return False
finally:
os.chdir(original_cwd)
def list_project_files(project_dir):
"""List key files in the project."""
print("\n Key files:")
key_files = [
"requirements.txt", "Dockerfile", "docker-compose.yml",
"package.json", "vite.config.js", "settings/base.py",
"manage.py"
]
for root, dirs, files in os.walk(project_dir):
# Skip hidden and common dirs
dirs[:] = [d for d in dirs if not d.startswith('.') and d not in ('__pycache__', 'node_modules')]
for f in files:
if f in key_files:
rel_path = os.path.relpath(os.path.join(root, f), project_dir)
print(f" - {rel_path}")
def main():
print("=" * 70)
print(" DJINIT - GENERATE REAL TEST PROJECTS")
print("=" * 70)
# Create test directory
os.makedirs("/tmp/djinit_tests", exist_ok=True)
# Define test projects
test_projects = [
# Structure: (name, structure, metadata)
("test_standard_basic", "standard", {}),
("test_standard_docker", "standard", {"use_docker": True}),
("test_standard_vite", "standard", {"use_vite": True}),
("test_standard_all", "standard", {"use_docker": True, "use_vite": True, "use_tailwind": True, "use_htmx": True}),
("test_predefined_basic", "predefined", {}),
("test_predefined_docker", "predefined", {"use_docker": True}),
("test_unified_basic", "unified", {}),
("test_unified_all", "unified", {"use_docker": True, "use_vite": True, "use_tailwind": True}),
("test_single_basic", "single", {}),
("test_single_docker", "single", {"use_docker": True}),
]
results = []
for name, structure, metadata in test_projects:
print(f"\n{'─' * 70}")
print(f" Creating: {name}")
print(f" Structure: {structure}")
print(f" Features: {list(metadata.keys()) if metadata else ['basic']}")
success = create_test_project(name, structure, metadata)
results.append((name, success))
if success:
list_project_files(f"/tmp/djinit_tests/{name}")
# Summary
print("\n" + "=" * 70)
print(" SUMMARY")
print("=" * 70)
passed = sum(1 for _, s in results if s)
total = len(results)
for name, success in results:
status = "✓ PASS" if success else "✗ FAIL"
print(f" {status}: {name}")
print(f"\n Total: {passed}/{total} passed")
if passed == total:
print("\n 🎉 All tests passed!")
else:
print("\n ⚠️ Some tests failed!")
# Show created directories
print("\n" + "=" * 70)
print(" CREATED PROJECTS")
print("=" * 70)
for name, _ in results:
print(f" /tmp/djinit_tests/{name}")
if __name__ == "__main__":
main()
+322
View File
@@ -0,0 +1,322 @@
#!/usr/bin/env python3
"""
Test script to show hello world examples for all project structures and cases.
Run from the djinit project root: PYTHONPATH=src python3 examples/test_all_structures.py
"""
import os
import sys
sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..', 'src'))
from djinit.templater import template_engine
def print_section(title):
print("\n" + "=" * 70)
print(f" {title}")
print("=" * 70)
def print_subsection(title):
print(f"\n{'─' * 70}")
print(f" {title}")
print(f"{'─' * 70}")
# Define all test cases
CASES = [
("Basic (no optional features)", {
"use_docker": False, "use_vite": False, "use_tailwind": False,
"use_htmx": False, "database_type": "postgresql", "use_database_url": True
}),
("Docker only", {
"use_docker": True, "use_vite": False, "use_tailwind": False,
"use_htmx": False, "database_type": "postgresql", "use_database_url": True
}),
("Vite/React only", {
"use_docker": False, "use_vite": True, "use_tailwind": False,
"use_htmx": False, "database_type": "postgresql", "use_database_url": True
}),
("Docker + Vite", {
"use_docker": True, "use_vite": True, "use_tailwind": False,
"use_htmx": False, "database_type": "postgresql", "use_database_url": True
}),
("Tailwind only", {
"use_docker": False, "use_vite": False, "use_tailwind": True,
"use_htmx": False, "database_type": "postgresql", "use_database_url": True
}),
("HTMX only", {
"use_docker": False, "use_vite": False, "use_tailwind": False,
"use_htmx": True, "database_type": "postgresql", "use_database_url": True
}),
("Tailwind + HTMX", {
"use_docker": False, "use_vite": False, "use_tailwind": True,
"use_htmx": True, "database_type": "postgresql", "use_database_url": True
}),
("All: Docker + Vite + Tailwind + HTMX + PostgreSQL", {
"use_docker": True, "use_vite": True, "use_tailwind": True,
"use_htmx": True, "database_type": "postgresql", "use_database_url": True
}),
("All: Docker + Vite + Tailwind + HTMX + MySQL", {
"use_docker": True, "use_vite": True, "use_tailwind": True,
"use_htmx": True, "database_type": "mysql", "use_database_url": True
}),
]
STRUCTURES = [
("standard", "config", "Standard Structure (default Django layout)"),
("predefined", "config", "Predefined Structure (apps/users, apps/core, api/)"),
("unified", "core", "Unified Structure (core/, apps/core, apps/api)"),
("single", "myproject", "Single Folder Layout (everything in one folder)"),
]
def show_file_tree(struct_type, case_name, metadata):
"""Show expected file tree for a structure + case combination."""
module_name = {
"standard": "config",
"predefined": "config",
"unified": "core",
"single": "myproject"
}[struct_type]
features = []
if metadata.get("use_docker"): features.append("Docker")
if metadata.get("use_vite"): features.append("Vite")
if metadata.get("use_tailwind"): features.append("Tailwind")
if metadata.get("use_htmx"): features.append("HTMX")
features.append(metadata.get("database_type", "postgresql").upper())
print(f" Features: {', '.join(features)}")
print(f" Project: myproject/")
print(f" Module: {module_name}/")
indent = " "
# Always present
print(f"{indent}├── .env.sample")
print(f"{indent}├── .gitignore")
print(f"{indent}├── requirements.txt")
print(f"{indent}├── pyproject.toml")
print(f"{indent}├── Procfile")
print(f"{indent}├── justfile")
print(f"{indent}├── runtime.txt")
if metadata.get("use_docker"):
print(f"{indent}├── Dockerfile")
print(f"{indent}├── docker-compose.yml")
print(f"{indent}├── .dockerignore")
if struct_type == "standard":
print(f"{indent}├── config/")
print(f"{indent}│ ├── __init__.py")
print(f"{indent}│ ├── settings/")
print(f"{indent}│ │ ├── __init__.py")
print(f"{indent}│ │ ├── base.py")
print(f"{indent}│ │ ├── development.py")
print(f"{indent}│ │ └── production.py")
print(f"{indent}│ ├── urls.py")
print(f"{indent}│ ├── wsgi.py")
print(f"{indent}│ └── asgi.py")
print(f"{indent}├── users/")
print(f"{indent}│ ├── __init__.py")
print(f"{indent}│ ├── models.py")
print(f"{indent}│ ├── views.py")
print(f"{indent}│ ├── urls.py")
print(f"{indent}│ └── apps.py")
print(f"{indent}└── manage.py")
elif struct_type == "predefined":
print(f"{indent}├── config/")
print(f"{indent}│ ├── __init__.py")
print(f"{indent}│ ├── settings/")
print(f"{indent}│ │ ├── __init__.py")
print(f"{indent}│ │ ├── base.py")
print(f"{indent}│ │ ├── development.py")
print(f"{indent}│ │ └── production.py")
print(f"{indent}│ ├── urls.py")
print(f"{indent}│ ├── wsgi.py")
print(f"{indent}│ └── asgi.py")
print(f"{indent}├── apps/")
print(f"{indent}│ ├── __init__.py")
print(f"{indent}│ ├── core/")
print(f"{indent}│ │ ├── __init__.py")
print(f"{indent}│ │ ├── utils/")
print(f"{indent}│ │ ├── mixins/")
print(f"{indent}│ │ └── middleware/")
print(f"{indent}│ └── users/")
print(f"{indent}│ ├── __init__.py")
print(f"{indent}│ └── apps.py")
print(f"{indent}├── api/")
print(f"{indent}│ ├── __init__.py")
print(f"{indent}│ ├── urls.py")
print(f"{indent}│ └── v1/")
print(f"{indent}│ ├── __init__.py")
print(f"{indent}│ └── urls.py")
print(f"{indent}└── manage.py")
elif struct_type == "unified":
print(f"{indent}├── core/")
print(f"{indent}│ ├── __init__.py")
print(f"{indent}│ ├── settings/")
print(f"{indent}│ │ ├── __init__.py")
print(f"{indent}│ │ ├── base.py")
print(f"{indent}│ │ ├── development.py")
print(f"{indent}│ │ └── production.py")
print(f"{indent}│ ├── urls.py")
print(f"{indent}│ ├── wsgi.py")
print(f"{indent}│ └── asgi.py")
print(f"{indent}├── apps/")
print(f"{indent}│ ├── __init__.py")
print(f"{indent}│ ├── apps.py")
print(f"{indent}│ ├── api/")
print(f"{indent}│ │ ├── __init__.py")
print(f"{indent}│ │ ├── urls.py")
print(f"{indent}│ │ └── v1/")
print(f"{indent}│ │ ├── __init__.py")
print(f"{indent}│ │ └── urls.py")
print(f"{indent}│ ├── models/")
print(f"{indent}│ ├── views/")
print(f"{indent}│ ├── serializers/")
print(f"{indent}│ ├── tests/")
print(f"{indent}│ └── urls/")
print(f"{indent}└── manage.py")
else: # single
print(f"{indent}├── myproject/")
print(f"{indent}│ ├── __init__.py")
print(f"{indent}│ ├── settings/")
print(f"{indent}│ │ ├── __init__.py")
print(f"{indent}│ │ ├── base.py")
print(f"{indent}│ │ ├── development.py")
print(f"{indent}│ │ └── production.py")
print(f"{indent}│ ├── urls.py")
print(f"{indent}│ ├── wsgi.py")
print(f"{indent}│ ├── asgi.py")
print(f"{indent}│ ├── api/")
print(f"{indent}│ ├── models/")
print(f"{indent}│ ├── admin/")
print(f"{indent}│ └── tests/")
print(f"{indent}└── manage.py")
if metadata.get("use_vite"):
print(f"{indent}├── frontend/")
print(f"{indent}│ ├── index.html")
print(f"{indent}│ ├── vite.config.js")
print(f"{indent}│ ├── package.json")
print(f"{indent}│ └── src/")
print(f"{indent}│ ├── main.jsx")
print(f"{indent}│ ├── App.jsx")
print(f"{indent}│ └── index.css")
print(f"{indent}└── static/")
if metadata.get("use_tailwind"):
print(f"{indent}├── static/")
print(f"{indent}│ └── css/")
print(f"{indent}└── templates/")
def show_template_examples():
"""Show actual template content for key files."""
print_section("TEMPLATE CONTENT EXAMPLES")
# 1. Requirements.txt examples
print_subsection("1. requirements.txt - Basic (No optional features)")
ctx = {"use_vite": False, "use_tailwind": False, "use_htmx": False,
"database_type": "postgresql", "use_database_url": True}
print(template_engine.render_template("project/requirements-tpl", ctx))
print_subsection("2. requirements.txt - All Features (PostgreSQL)")
ctx = {"use_vite": True, "use_tailwind": True, "use_htmx": True,
"database_type": "postgresql", "use_database_url": True}
print(template_engine.render_template("project/requirements-tpl", ctx))
print_subsection("3. requirements.txt - All Features (MySQL)")
ctx = {"use_vite": True, "use_tailwind": True, "use_htmx": True,
"database_type": "mysql", "use_database_url": True}
print(template_engine.render_template("project/requirements-tpl", ctx))
# 4. Settings examples
print_subsection("4. settings/base.py - With Vite enabled")
ctx = {"project_name": "config", "app_names": ["users"],
"use_vite": True, "use_tailwind": False, "use_htmx": False,
"use_database_url": True, "database_type": "postgresql"}
result = template_engine.render_template("config/settings/base.py-tpl", ctx)
for line in result.split('\n'):
if 'django_vite' in line or 'DJANGO_VITE' in line:
print(line)
print_subsection("5. settings/base.py - With Tailwind enabled")
ctx = {"project_name": "config", "app_names": ["users"],
"use_vite": False, "use_tailwind": True, "use_htmx": False,
"use_database_url": True, "database_type": "postgresql"}
result = template_engine.render_template("config/settings/base.py-tpl", ctx)
for line in result.split('\n'):
if 'tailwind' in line.lower() or 'daisyui' in line.lower():
print(line)
# 6. Dockerfile example
print_subsection("6. Dockerfile (PostgreSQL)")
ctx = {"project_name": "myproject", "module_name": "config", "database_type": "postgresql"}
print(template_engine.render_template("project/Dockerfile-tpl", ctx))
print_subsection("7. Dockerfile (MySQL)")
ctx = {"project_name": "myproject", "module_name": "config", "database_type": "mysql"}
print(template_engine.render_template("project/Dockerfile-tpl", ctx))
# 8. docker-compose.yml examples
print_subsection("8. docker-compose.yml (PostgreSQL)")
ctx = {"project_name": "myproject", "database_type": "postgresql", "use_database_url": True}
print(template_engine.render_template("project/docker-compose.yml-tpl", ctx))
# 9. vite.config.js
print_subsection("9. vite.config.js")
ctx = {"project_name": "myproject", "module_name": "config"}
print(template_engine.render_template("project/vite.config.js-tpl", ctx))
# 10. package.json
print_subsection("10. package.json")
print(template_engine.render_template("project/package.json-tpl", ctx))
# 11. Frontend examples
print_subsection("11. frontend/index.html")
print(template_engine.render_template("project/frontend/index.html-tpl", ctx))
print_subsection("12. frontend/src/App.jsx")
print(template_engine.render_template("project/frontend/src/App.jsx-tpl", ctx))
def main():
print_section("DJINIT - ALL STRUCTURES & CASES")
# Show all structure + case combinations
for struct_type, module_name, struct_desc in STRUCTURES:
print_section(struct_desc)
for case_name, metadata in CASES:
print_subsection(case_name)
show_file_tree(struct_type, case_name, metadata)
# Show template content examples
show_template_examples()
print("\n" + "=" * 70)
print(" ALL STRUCTURES & CASES TESTED SUCCESSFULLY!")
print("=" * 70)
print("\nSummary:")
print(f" • {len(STRUCTURES)} project structures")
print(f" • {len(CASES)} feature combinations")
print(f" • Total: {len(STRUCTURES) * len(CASES)} unique configurations")
print("\nEach combination generates:")
print(" - Django project files based on structure type")
print(" - Optional: Docker files (Dockerfile, docker-compose.yml)")
print(" - Optional: Vite/React frontend (vite.config.js, package.json, etc.)")
print(" - Optional: Tailwind CSS configuration")
print(" - Optional: HTMX integration")
if __name__ == "__main__":
main()