From a43e35e925752f831e8085e9cb50f670ddd4e909 Mon Sep 17 00:00:00 2001 From: S4NKALP Date: Sun, 10 May 2026 23:58:12 +0545 Subject: [PATCH] feat(examples): add bug detection script for djinit templates MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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) --- examples/bug_check.py | 246 ++++++++++++++++++++++++ examples/full_test.py | 189 +++++++++++++++++++ examples/generate_projects.py | 186 ++++++++++++++++++ examples/test_all_structures.py | 322 ++++++++++++++++++++++++++++++++ 4 files changed, 943 insertions(+) create mode 100644 examples/bug_check.py create mode 100644 examples/full_test.py create mode 100644 examples/generate_projects.py create mode 100644 examples/test_all_structures.py diff --git a/examples/bug_check.py b/examples/bug_check.py new file mode 100644 index 0000000..e19287d --- /dev/null +++ b/examples/bug_check.py @@ -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() \ No newline at end of file diff --git a/examples/full_test.py b/examples/full_test.py new file mode 100644 index 0000000..c4c3b47 --- /dev/null +++ b/examples/full_test.py @@ -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() \ No newline at end of file diff --git a/examples/generate_projects.py b/examples/generate_projects.py new file mode 100644 index 0000000..fbabcc2 --- /dev/null +++ b/examples/generate_projects.py @@ -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() \ No newline at end of file diff --git a/examples/test_all_structures.py b/examples/test_all_structures.py new file mode 100644 index 0000000..8685ff8 --- /dev/null +++ b/examples/test_all_structures.py @@ -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() \ No newline at end of file