Coverage for session_buddy / core / lifecycle / project_context.py: 27.66%
39 statements
« prev ^ index » next coverage.py v7.13.1, created at 2026-01-04 00:43 -0800
« prev ^ index » next coverage.py v7.13.1, created at 2026-01-04 00:43 -0800
1"""Project context analysis for session management.
3This module provides utilities for analyzing project structure, detecting
4frameworks, and gathering project health indicators.
5"""
7from __future__ import annotations
9from contextlib import suppress
10from typing import TYPE_CHECKING
12from session_buddy.utils.git_operations import is_git_repository
14if TYPE_CHECKING:
15 from pathlib import Path
18def check_readme_exists(project_dir: Path) -> bool:
19 """Check if README file exists."""
20 return any(
21 (project_dir / name).exists()
22 for name in ("README.md", "README.rst", "README.txt", "readme.md")
23 )
26def check_venv_exists(project_dir: Path) -> bool:
27 """Check if virtual environment exists."""
28 return any(
29 (project_dir / name).exists() for name in (".venv", "venv", ".env", "env")
30 )
33def check_tests_exist(project_dir: Path) -> bool:
34 """Check if test directories exist."""
35 return any((project_dir / name).exists() for name in ("tests", "test", "testing"))
38def check_docs_exist(project_dir: Path) -> bool:
39 """Check if documentation directories exist."""
40 return any((project_dir / name).exists() for name in ("docs", "documentation"))
43def check_ci_cd_exists(project_dir: Path) -> bool:
44 """Check if CI/CD configuration exists."""
45 return any(
46 (project_dir / name).exists()
47 for name in (".github", ".gitlab-ci.yml", ".travis.yml", "Jenkinsfile")
48 )
51def get_basic_project_indicators(project_dir: Path) -> dict[str, bool]:
52 """Get basic project structure indicators."""
53 return {
54 "has_pyproject_toml": (project_dir / "pyproject.toml").exists(),
55 "has_setup_py": (project_dir / "setup.py").exists(),
56 "has_requirements_txt": (project_dir / "requirements.txt").exists(),
57 "has_readme": check_readme_exists(project_dir),
58 "has_git_repo": is_git_repository(project_dir),
59 "has_venv": check_venv_exists(project_dir),
60 "has_tests": check_tests_exist(project_dir),
61 "has_src_structure": (project_dir / "src").exists(),
62 "has_docs": check_docs_exist(project_dir),
63 "has_ci_cd": check_ci_cd_exists(project_dir),
64 }
67def check_framework_imports(content: str, indicators: dict[str, bool]) -> None:
68 """Check for framework imports in file content."""
69 if "import fastapi" in content or "from fastapi" in content:
70 indicators["uses_fastapi"] = True
71 if "import django" in content or "from django" in content:
72 indicators["uses_django"] = True
73 if "import flask" in content or "from flask" in content:
74 indicators["uses_flask"] = True
77def detect_python_frameworks(
78 python_files: list[Path], indicators: dict[str, bool]
79) -> None:
80 """Detect Python frameworks from file content."""
81 for py_file in python_files[:10]: # Sample first 10 files
82 try:
83 with py_file.open("r", encoding="utf-8") as f:
84 content = f.read(1000) # Read first 1000 chars
85 check_framework_imports(content, indicators)
86 except (UnicodeDecodeError, PermissionError):
87 continue
90def add_python_context_indicators(
91 project_dir: Path, indicators: dict[str, bool]
92) -> None:
93 """Add Python-specific context indicators."""
94 with suppress(Exception):
95 python_files = list(project_dir.glob("**/*.py"))
96 indicators["has_python_files"] = len(python_files) > 0
97 detect_python_frameworks(python_files, indicators)
100async def analyze_project_context(project_dir: Path) -> dict[str, bool]:
101 """Analyze project directory for common indicators and patterns."""
102 indicators = get_basic_project_indicators(project_dir)
103 add_python_context_indicators(project_dir, indicators)
104 return indicators