Add framework detector and setup generator
Some checks failed
CI / test (push) Failing after 11s
CI / build (push) Has been skipped

This commit is contained in:
2026-01-29 13:22:24 +00:00
parent fae0c30272
commit 135be8a628

View File

@@ -0,0 +1,195 @@
"""Setup instruction generator for project setup."""
import json
import re
from pathlib import Path
from typing import Any
class SetupInstructionGenerator:
"""Generates setup instructions based on detected package managers."""
def __init__(self, project_path: Path):
self.project_path = project_path
def generate(self) -> dict[str, Any]:
"""Generate comprehensive setup instructions."""
instructions: dict[str, Any] = {
"install_commands": [],
"build_commands": [],
"run_commands": [],
"test_commands": [],
"environment_variables": [],
"notes": [],
}
package_manager = self._detect_package_manager()
if package_manager == "npm":
self._generate_npm_instructions(instructions)
elif package_manager == "pip":
self._generate_pip_instructions(instructions)
elif package_manager == "poetry":
self._generate_poetry_instructions(instructions)
elif package_manager == "cargo":
self._generate_cargo_instructions(instructions)
elif package_manager == "maven":
self._generate_maven_instructions(instructions)
elif package_manager == "go":
self._generate_go_instructions(instructions)
self._add_generic_instructions(instructions)
self._detect_env_vars(instructions)
return instructions
def _detect_package_manager(self) -> str | None:
"""Detect which package manager is used."""
indicators = {
"npm": ["package.json", "package-lock.json"],
"pip": ["requirements.txt", "Pipfile"],
"poetry": ["pyproject.toml", "poetry.lock"],
"cargo": ["Cargo.toml", "Cargo.lock"],
"maven": ["pom.xml"],
"go": ["go.mod", "go.sum"],
}
for pm, files in indicators.items():
for f in files:
if (self.project_path / f).exists():
return pm
return None
def _generate_npm_instructions(self, instructions: dict[str, Any]) -> None:
"""Generate npm-specific instructions."""
pkg_json = self.project_path / "package.json"
if pkg_json.exists():
content = self._safe_read_file(pkg_json)
if content:
try:
pkg = json.loads(content)
deps = pkg.get("dependencies", {})
dev_deps = pkg.get("devDependencies", {})
instructions["install_commands"].append("npm install")
if "scripts" in pkg:
scripts = pkg["scripts"]
if "start" in scripts:
instructions["run_commands"].append("npm start")
if "dev" in scripts:
instructions["run_commands"].append("npm run dev")
if "build" in scripts:
instructions["build_commands"].append("npm run build")
if "test" in scripts:
instructions["test_commands"].append("npm test")
if "react-scripts" in dev_deps or "next" in deps:
instructions["notes"].append("This appears to be a React/Next.js project")
except json.JSONDecodeError:
pass
instructions["install_commands"].extend([
"npm install",
"npm install --save-dev <additional-deps>",
])
instructions["run_commands"].append("npm start")
instructions["build_commands"].append("npm run build")
instructions["test_commands"].append("npm test")
def _generate_pip_instructions(self, instructions: dict[str, Any]) -> None:
"""Generate pip-specific instructions."""
requirements = self.project_path / "requirements.txt"
instructions["install_commands"].extend([
"python -m venv venv",
"source venv/bin/activate # On Windows: venv\\Scripts\\activate",
"pip install -r requirements.txt",
])
if (self.project_path / "manage.py").exists():
instructions["run_commands"].append("python manage.py runserver")
instructions["build_commands"].append("python manage.py migrate")
instructions["test_commands"].append("python -m pytest")
def _generate_poetry_instructions(self, instructions: dict[str, Any]) -> None:
"""Generate Poetry-specific instructions."""
instructions["install_commands"].extend([
"poetry install",
"poetry install --with dev",
])
pyproject = self.project_path / "pyproject.toml"
if pyproject.exists():
content = self._safe_read_file(pyproject)
if content and 'scripts' in content:
scripts_match = re.search(r'scripts\s*=\s*\{([^}]+)\}', content)
if scripts_match:
script_name = scripts_match.group(1).split('=')[0].strip().strip('"').strip("'")
instructions["run_commands"].append(f"poetry run {script_name}")
instructions["test_commands"].append("poetry run pytest")
def _generate_cargo_instructions(self, instructions: dict[str, Any]) -> None:
"""Generate Cargo-specific instructions."""
instructions["install_commands"].append("cargo build")
instructions["run_commands"].append("cargo run")
instructions["build_commands"].append("cargo build --release")
instructions["test_commands"].append("cargo test")
def _generate_maven_instructions(self, instructions: dict[str, Any]) -> None:
"""Generate Maven-specific instructions."""
instructions["install_commands"].append("mvn clean install")
instructions["run_commands"].append("mvn spring-boot:run")
instructions["build_commands"].append("mvn package")
instructions["test_commands"].append("mvn test")
def _generate_go_instructions(self, instructions: dict[str, Any]) -> None:
"""Generate Go-specific instructions."""
instructions["install_commands"].extend([
"go mod download",
"go mod tidy",
])
main_go = self.project_path / "main.go"
if main_go.exists():
instructions["run_commands"].append("go run main.go")
instructions["build_commands"].append("go build -o app main.go")
instructions["test_commands"].append("go test ./...")
def _add_generic_instructions(self, instructions: dict[str, Any]) -> None:
"""Add generic fallback instructions."""
if not instructions["install_commands"]:
instructions["install_commands"].append("# Install dependencies based on your project type")
if not instructions["run_commands"]:
instructions["run_commands"].append("# Run command depends on your framework")
if not instructions["build_commands"]:
instructions["build_commands"].append("# Build command depends on your project")
if not instructions["test_commands"]:
instructions["test_commands"].append("# Test command depends on your project")
def _detect_env_vars(self, instructions: dict[str, Any]) -> None:
"""Detect required environment variables from config files."""
env_example = self.project_path / ".env.example"
if env_example.exists():
content = self._safe_read_file(env_example)
if content:
vars_found = re.findall(r"^([A-Z_]+)=", content, re.MULTILINE)
instructions["environment_variables"] = vars_found
instructions["notes"].append("Copy .env.example to .env and configure values")
def _safe_read_file(self, path: Path) -> str | None:
"""Safely read a file."""
try:
return path.read_text(encoding="utf-8")
except (IOError, UnicodeDecodeError):
return None