feat: extend analysis pipeline for Python codebases and frameworks

- project-scanner: detect Python frameworks from requirements.txt,
  pyproject.toml, setup.py, Pipfile (django, fastapi, flask, sqlalchemy,
  celery, pydantic, etc.); add pyproject.toml to project name extraction

- SKILL.md: expand Python entry points (manage.py, app.py, wsgi.py,
  asgi.py, run.py, __main__.py); add FastAPI and Flask framework guidance
  to Phase 2 and Phase 4 inline hints; wire addendum file injection for
  Django, FastAPI, and Flask when detected

- architecture-analyzer: add __init__.py and manage.py as entry-point
  file-level patterns; add Python directory patterns (migrations, signals,
  serializers, management, templatetags); clarify *.d.ts is TS-only

- tour-builder: add Python entry point filename patterns to +3 scoring
  (manage.py, app.py, wsgi.py, asgi.py, run.py, __main__.py)

- file-analyzer: add __init__.py barrel/entry-point detection alongside
  index.ts; show Python script execution alternative in example

- new: django-analyzer-addendum.md — canonical file roles, edge patterns
  (URL routing graph, signal wiring, ORM relationships), layer guide, and
  language lesson patterns for Django projects

- new: fastapi-analyzer-addendum.md — canonical file roles, DI tree edge
  patterns, layer guide, and language lesson patterns for FastAPI and Flask

- new: PYTHON-SUPPORT-CHANGES.md — reviewer doc covering every change,
  rationale, regression risk, and a testing checklist

https://claude.ai/code/session_015ihoTRnr7yYx3TkcadKYbn
This commit is contained in:
Claude
2026-03-21 16:00:03 +00:00
Unverified
parent 9866fccae9
commit 46fb114b14
8 changed files with 415 additions and 12 deletions
@@ -0,0 +1,208 @@
# Python Codebase Support — Change Review Guide
This document explains every change made to add Python and Python framework support. It is written for a reviewer who wants to verify correctness, spot regressions, and understand the rationale for each decision.
---
## Background: What Was Wrong
The tool worked well for TypeScript/JavaScript codebases. For Python codebases it would:
- Fail to detect frameworks (Django, FastAPI, Flask) — `frameworks: []` always
- Miss common Python entry points (`manage.py`, `app.py`, `wsgi.py`) — defaulting to no entry point
- Score Python entry points much lower than TS equivalents in the tour builder (4 Python patterns vs 8 JS/TS patterns)
- Miss Python's `__init__.py` as a barrel/entry-point equivalent (only `index.ts`/`index.js` were recognized)
- Have no layer guidance for FastAPI or Flask (only Django had a brief mention)
- Ignore `pyproject.toml` for project name extraction
The bias was **only in agent prompts** (markdown files). The graph schema, dashboard, search engine, and core plugin architecture are language-agnostic and required no changes.
---
## Files Changed
### 1. `project-scanner-prompt.md`
**What changed:**
**Step 5 (Framework Detection)** — Extended the Python manifest reading from "confirms Python project" to actually detecting frameworks:
- `requirements.txt`: now reads line-by-line, strips version specifiers, and matches against a Python framework keyword list: `django`, `djangorestframework`, `fastapi`, `flask`, `sqlalchemy`, `alembic`, `celery`, `pydantic`, `uvicorn`, `gunicorn`, `aiohttp`, `tornado`, `starlette`, `pytest`, `hypothesis`, `channels`
- `pyproject.toml`: now parses `[project].dependencies` and `[tool.poetry.dependencies]`, applies the same keyword matching, and also checks for `[tool.pytest.ini_options]` (pytest) and `[tool.django]` (Django)
- `setup.py`, `setup.cfg`, `Pipfile`: now apply the same Python framework keyword matching
**Step 7 (Project Name)** — Added `pyproject.toml` to the priority order between `go.mod` and directory name. Checks `[project].name` first, then `[tool.poetry].name`.
**Why:** Without framework detection, `frameworks: []` is passed to every downstream agent. The framework-specific guidance injected in Phase 2 and Phase 4 of SKILL.md is only useful when `frameworks` is non-empty.
**Regression risk:** None. The JS framework detection in `package.json` is unchanged. The Python additions are additive.
**How to verify:** Run `/understand` on a Django project with `requirements.txt` containing `django`. Check that `scan-result.json` has `frameworks: ["Django"]`.
---
### 2. `SKILL.md`
**What changed:**
**Phase 0 (entry point detection, line 57)** — Added Python entry points to the pattern list:
- Before: `src/index.ts`, `src/main.ts`, `src/App.tsx`, `main.py`, `main.go`, `src/main.rs`, `index.js`
- After: added `manage.py`, `app.py`, `wsgi.py`, `asgi.py`, `run.py`, `__main__.py`
**Why:** A Django project's real entry point is `manage.py`. A FastAPI/Flask project uses `app.py` or `run.py`. Without these, `$ENTRY_POINT` is empty for most Python projects, and the tour builder gets no starting hint.
**Phase 2 (file-analyzer framework guidance)** — Extended the inline framework hints:
- Django: added `serializers.py`, `signals.py`, `admin.py`, `migrations/` descriptions
- Added FastAPI: describes `@router` decorator files, Pydantic schemas, `Depends()` providers
- Added Flask: describes `@blueprint.route`, `blueprints/`, SQLAlchemy `models.py`
- Added addendum injection: if `Django` detected, reads `./django-analyzer-addendum.md` and appends to the file-analyzer prompt. If `FastAPI` or `Flask` detected, reads `./fastapi-analyzer-addendum.md` and appends.
**Phase 4 (architecture-analyzer framework hints)** — Extended the inline layer hints:
- Django: added `serializers.py`, `signals.py`, `migrations/` → specific layers
- Added FastAPI: router files → API, Pydantic schemas → Types, `dependencies.py` → Service, DB files → Data
- Added Flask: blueprint route files → API, `models.py` → Data, `forms.py` → UI, `extensions.py` → Config
- Added addendum injection: same logic as Phase 2
**Regression risk:** Low. The addendum injection only triggers when those frameworks are in the detected list. The inline guidance additions are additive strings — they don't change the structure of the injected context.
**How to verify:**
- Run on a FastAPI project: check `layers.json` has a `layer:types` or `layer:api` with Pydantic schema files assigned correctly
- Run on a TS project: check that no Django/FastAPI addendum content appears in the analysis (it shouldn't, since `frameworks` won't contain those values)
---
### 3. `architecture-analyzer-prompt.md`
**What changed:**
**Directory pattern table** — Added Python-specific directory names:
| Added | Pattern Label | Why |
|-------|---------------|-----|
| `migrations` | `data` | Django/Alembic migration directories hold schema history — Data Layer |
| `management`, `commands` | `config` | Django management command directories |
| `templatetags` | `utility` | Django custom template tag directories |
| `signals` | `service` | Signal handler modules — cross-cutting service logic |
| `serializers` | `api` | DRF serializer directories |
**File-level pattern matching** — Three changes:
1. Added `test_*.py` to the test pattern (Python's `pytest` naming convention)
2. Added `__init__.py` at a directory root → `entry` pattern (Python package barrel equivalent of `index.ts`)
3. Added `manage.py``entry` and `wsgi.py`/`asgi.py``config`
4. Clarified `*.d.ts → types` with "(TypeScript declaration files only)" — making it explicit this is TS-specific so an LLM doesn't misapply it to Python
**Why:** Without `__init__.py → entry`, the architecture analyzer would never recognize any Python file as an entry point via file-level patterns. The `hooks` pattern label was left as-is (it won't trigger on Python projects since they don't conventionally have a `hooks/` directory).
**Note on Node.js script:** The architecture analyzer's structural analysis script is hardcoded to `node`. This is correct to leave as-is — the script processes the JSON graph structure (file nodes, import edges), not the source language of the codebase being analyzed. The script's input/output is always JSON regardless of whether the project is Python or TypeScript.
**Regression risk:** Very low. Added rows to the directory pattern table and clarified file-level pattern descriptions. No existing patterns were removed or modified.
**How to verify:** Run on a Django project. Check that `migrations/` directory files land in `layer:data` and that `manage.py` gets tagged `entry`.
---
### 4. `tour-builder-prompt.md`
**What changed:**
**Entry point candidate scoring (Section C)** — Added Python entry points to the +3 filename list:
- Added: `manage.py`, `app.py`, `wsgi.py`, `asgi.py`, `run.py`, `__main__.py`
Before this change, the entry point scoring had 8 TS/JS patterns vs 4 for all other languages. After: 8 TS/JS + 6 Python + 4 others.
**Why:** The tour builder uses entry point scores to decide Step 1 of the tour. For a Django project where `manage.py` exists, it should score highly. Without this, the tour might start from a random high-fan-in utility file instead of the actual entry point.
**The `languageLesson` example** was left as-is (TypeScript barrel files). This is just an illustrative example in the output format section — it does not affect how Python tours are generated. The language lessons section already lists Python-specific patterns (decorators, generators, context managers, metaclasses, protocols).
**Regression risk:** None. The scoring list is additive. TS/JS entry points retain their +3 scores.
**How to verify:** Run on a Django project. Check that `tour.json` starts from `manage.py` or `apps.py`/`wsgi.py` rather than a utility file.
---
### 5. `file-analyzer-prompt.md`
**What changed:**
**Tags indicators — barrel/entry-point detection** — Extended the `index.ts` rule:
- Before: `Named index.ts at a directory root with re-exports = entry-point`
- After: Added `__init__.py` at a package root with imports or re-exports = `entry-point`, and `manage.py` = `entry-point`
**Script execution example** — Added the Python equivalent command alongside the Node.js example. The base prompt already says "Choose the best language for this task — Node.js is recommended for TypeScript/JavaScript projects, Python for Python projects" (line 15), but the execution example only showed `node`. This created a contradiction. Now both are shown.
**Regression risk:** None. Additive changes only.
**How to verify:** Run on a Python project with a package structure. Check that `__init__.py` files at package roots get the `entry-point` or `barrel` tag rather than being treated as empty boilerplate files.
---
## New Files Created
### `django-analyzer-addendum.md`
A detailed reference injected into the file-analyzer and architecture-analyzer when Django is detected. Contains:
- Canonical file roles table (15+ Django file types with appropriate tags)
- Edge patterns to look for (URL routing graph, signal wiring, ORM relationships, serializer→model binding)
- Layer assignment guide (7 layers: api, data, service, ui, middleware, config, test)
- Notable `languageLesson` patterns (fat models, ORM lazy evaluation, CBV mixins, signal anti-patterns, app isolation)
**How it's injected:** SKILL.md reads this file and appends it to the base `file-analyzer-prompt.md` and `architecture-analyzer-prompt.md` content when `Django` appears in the detected frameworks list.
### `fastapi-analyzer-addendum.md`
A detailed reference for FastAPI and Flask projects, injected when either framework is detected. Contains two sections:
**FastAPI section:**
- Canonical file roles (router files, Pydantic schemas, CRUD, dependencies, database session)
- Edge patterns (router inclusion chain, DI tree, Pydantic inheritance, CRUD→model binding)
- Layer assignment guide (7 layers)
- Notable `languageLesson` patterns (DI as composition, Pydantic validation, async vs sync, route order)
**Flask section:**
- Canonical file roles (blueprints, application factory, WTForms, Marshmallow)
- Edge patterns (blueprint registration, extension coupling, before/after request hooks)
- Layer assignment guide
- Notable `languageLesson` patterns (factory pattern, blueprint modularity, extension `init_app` protocol)
**How it's injected:** Same mechanism as the Django addendum — SKILL.md appends it when `FastAPI` or `Flask` is in the detected frameworks list.
---
## What Was NOT Changed (And Why)
| Component | Rationale |
|-----------|-----------|
| Graph schema (`types.ts`, `schema.ts`) | Already language-agnostic. All 18 edge types work for Python patterns. |
| `packages/core/src/plugins/tree-sitter-plugin.ts` | Still TS/JS only. Adding Python tree-sitter support is Phase 3 (separate PR). |
| `packages/core/src/plugins/registry.ts` | Extension map already has `.py → python`. A Python plugin will register here in Phase 3. |
| `packages/core/src/analyzer/language-lesson.ts` | Concept detection patterns. Phase 3 work. |
| Dashboard, search engine, skills | Already language-agnostic. |
| `tour-builder-prompt.md` language lessons example | The TypeScript barrel file example is illustrative only. Python tours will produce Python-specific `languageLesson` strings based on the language-lessons list (which already includes Python patterns). |
| Architecture analyzer `node` script execution | The script analyzes the graph JSON, not the source language. `node` is always correct here. |
| `hooks` directory pattern label | React-specific but harmless — Python projects don't conventionally have `hooks/` directories, so this label will never trigger on Python codebases. |
---
## Testing Checklist for Reviewer
For a Django project (e.g., a real Django app with `requirements.txt`):
- [ ] `scan-result.json` has `frameworks: ["Django"]` (or similar)
- [ ] `manage.py` is detected as `$ENTRY_POINT` in SKILL.md Phase 0
- [ ] `manage.py` node gets tags including `entry-point`
- [ ] `urls.py` files get `api-handler`, `routing` tags
- [ ] `models.py` files get `data-model` tag
- [ ] `migrations/` directory files land in `layer:data`
- [ ] Tour Step 1 starts from `manage.py` or `wsgi.py`
- [ ] No TypeScript-specific guidance appears in the analysis output
For a FastAPI project:
- [ ] `scan-result.json` has `frameworks: ["FastAPI"]`
- [ ] Router files get `api-handler`, `routing` tags
- [ ] Pydantic schema files get `type-definition`, `serialization` tags
- [ ] `dependencies.py` or `deps.py` gets `service` tag
- [ ] `depends_on` edges appear between router files and their dependencies
- [ ] `layer:types` exists with schema files
For an existing TypeScript project (regression check):
- [ ] No Django/FastAPI addendum content appears in analysis
- [ ] `frameworks: ["React"]` (or whatever was there before) unchanged
- [ ] `src/index.ts` still detected as entry point
- [ ] All existing layer assignments and tour steps unchanged
@@ -54,7 +54,7 @@ Determine whether to run a full analysis or incremental update.
find $PROJECT_ROOT -maxdepth 2 -type f -not -path '*/node_modules/*' -not -path '*/.git/*' -not -path '*/dist/*' | head -100
```
Store as `$DIR_TREE`.
- Detect the project entry point by checking for common patterns: `src/index.ts`, `src/main.ts`, `src/App.tsx`, `main.py`, `main.go`, `src/main.rs`, `index.js`. Store first match as `$ENTRY_POINT`.
- Detect the project entry point by checking for common patterns (in order): `src/index.ts`, `src/main.ts`, `src/App.tsx`, `index.js`, `main.py`, `manage.py`, `app.py`, `wsgi.py`, `asgi.py`, `run.py`, `__main__.py`, `main.go`, `src/main.rs`. Store first match as `$ENTRY_POINT`.
---
@@ -98,7 +98,7 @@ After the subagent completes, read `$PROJECT_ROOT/.understand-anything/intermedi
Batch the file list from Phase 1 into groups of **5-10 files each** (aim for balanced batch sizes).
For each batch, dispatch a subagent using the prompt template at `./file-analyzer-prompt.md`. Run up to **3 subagents concurrently** using parallel dispatch. Read the template once, then for each batch pass the full template content as the subagent's prompt, appending the following additional context:
For each batch, dispatch a subagent using the prompt template at `./file-analyzer-prompt.md`. Run up to **3 subagents concurrently** using parallel dispatch. Read the template once. If any detected framework is `Django`, also read `./django-analyzer-addendum.md` and append its full content after the base template. If any detected framework is `FastAPI` or `Flask`, also read `./fastapi-analyzer-addendum.md` and append its full content after the base template. Then for each batch pass the combined template content as the subagent's prompt, appending the following additional context:
> **Additional context from main session:**
>
@@ -109,7 +109,9 @@ For each batch, dispatch a subagent using the prompt template at `./file-analyze
> Framework-specific guidance:
> - If React/Next.js: files in `app/` or `pages/` are routes, `components/` are UI, `lib/` or `utils/` are utilities
> - If Express/Fastify: files in `routes/` are API endpoints, `middleware/` is middleware, `models/` or `db/` is data
> - If Python Django: `views.py` are controllers, `models.py` is data, `urls.py` is routing, `templates/` is UI
> - If Python Django: `views.py` are controllers, `models.py` is data, `urls.py` is routing, `templates/` is UI, `serializers.py` is API serialization, `signals.py` is event wiring, `admin.py` is admin registration, `migrations/` is schema history
> - If Python FastAPI: files with `@router.get/post/...` decorators are endpoints, `schemas.py` or `models.py` with Pydantic classes are request/response types, `dependencies.py` or `deps.py` holds `Depends()` providers, `routers/` or `api/` groups route modules
> - If Python Flask: files with `@app.route` or `@blueprint.route` are endpoints, `blueprints/` or `views/` groups route modules, `models.py` with SQLAlchemy classes is data
> - If Go: `cmd/` is entry points, `internal/` is private packages, `pkg/` is public packages
>
> Use this context to produce more accurate summaries and better classify file roles.
@@ -158,7 +160,7 @@ Merge all file-analyzer results into a single set of nodes and edges. Then perfo
## Phase 4 — ARCHITECTURE
Dispatch a subagent using the prompt template at `./architecture-analyzer-prompt.md`. Read the template file and pass the full content as the subagent's prompt, appending the following additional context:
Dispatch a subagent using the prompt template at `./architecture-analyzer-prompt.md`. If any detected framework is `Django`, also read `./django-analyzer-addendum.md` and append its full content after the base template. If any detected framework is `FastAPI` or `Flask`, also read `./fastapi-analyzer-addendum.md` and append its full content after the base template. Pass the combined content as the subagent's prompt, appending the following additional context:
> **Additional context from main session:**
>
@@ -172,7 +174,9 @@ Dispatch a subagent using the prompt template at `./architecture-analyzer-prompt
> Framework-specific layer hints:
> - If React/Next.js: `app/` or `pages/` → UI Layer, `api/` → API Layer, `lib/` → Service Layer, `components/` → UI Layer
> - If Express: `routes/` → API Layer, `controllers/` → Service Layer, `models/` → Data Layer, `middleware/` → Middleware Layer
> - If Python Django: `views/` → API Layer, `models/` → Data Layer, `templates/` → UI Layer, `management/` → CLI Layer
> - If Python Django: `views/` or `views.py` → API Layer, `models/` or `models.py` → Data Layer, `templates/` → UI Layer, `management/` → CLI Layer, `serializers.py` → API Layer, `signals.py` → Event Layer, `migrations/` → Data Layer
> - If Python FastAPI: files with router decorators → API Layer, Pydantic schema files → Types Layer, `dependencies.py` or `deps.py` → Service Layer, `routers/` or `api/` → API Layer, database session/engine files → Data Layer
> - If Python Flask: files with `@blueprint.route` → API Layer, `models.py` → Data Layer, `forms.py` → UI Layer, `extensions.py` → Config Layer
> - If Go: `cmd/` → Entry Points, `internal/` → Service Layer, `pkg/` → Shared Library, `api/` → API Layer
>
> Use the directory tree and framework hints to inform layer assignments. Directory structure is strong evidence for layer boundaries.
@@ -82,11 +82,18 @@ Classify each directory name against known architectural patterns:
| `hooks` | `hooks` |
| `store`, `state`, `reducers`, `actions`, `slices` | `state` |
| `assets`, `static`, `public` | `assets` |
| `migrations` | `data` |
| `management`, `commands` | `config` |
| `templatetags` | `utility` |
| `signals` | `service` |
| `serializers` | `api` |
Also check file-level patterns:
- Files matching `*.test.*` or `*.spec.*` -> `test`
- Files matching `*.d.ts` -> `types`
- Files named `index.ts`/`index.js` at a package root -> `entry`
- Files matching `*.test.*` or `*.spec.*` or `test_*.py` -> `test`
- Files matching `*.d.ts` -> `types` (TypeScript declaration files only)
- Files named `index.ts`, `index.js`, or `__init__.py` at a package/directory root -> `entry`
- Files named `manage.py` at the project root -> `entry` (Django management entry point)
- Files named `wsgi.py` or `asgi.py` -> `config` (Python WSGI/ASGI server config)
**F. Dependency Direction**
@@ -0,0 +1,67 @@
# Django Framework Addendum
> Injected into file-analyzer and architecture-analyzer prompts when Django is detected.
> Do NOT use as a standalone prompt — always appended to the base prompt template.
## Django Project Structure
When analyzing a Django project, apply these additional conventions on top of the base analysis rules.
### Canonical File Roles
| File / Pattern | Role | Tags |
|---|---|---|
| `manage.py` | CLI entry point for dev server, migrations, management commands | `entry-point`, `config` |
| `*/settings.py`, `*/settings/*.py` | Project-wide configuration (DB, installed apps, middleware) | `config` |
| `*/urls.py` | URL routing — maps URL patterns to views | `api-handler`, `routing` |
| `*/views.py`, `*/views/*.py` | Request handlers (function-based or class-based views) | `api-handler`, `controller` |
| `*/models.py`, `*/models/*.py` | ORM models — map to database tables | `data-model` |
| `*/serializers.py` | DRF serializers — convert models to/from JSON | `serialization`, `api-handler` |
| `*/forms.py` | Django forms — validation and rendering logic | `validation`, `ui` |
| `*/admin.py` | Admin site registrations — exposes models in Django admin | `config` |
| `*/signals.py` | Signal handlers — cross-cutting side effects on model events | `event-handler` |
| `*/tasks.py` | Celery async task definitions | `service`, `event-handler` |
| `*/middleware.py`, `*/middleware/*.py` | Request/response middleware classes | `middleware` |
| `*/permissions.py` | DRF permission classes | `middleware`, `validation` |
| `*/filters.py` | DRF filter backends | `utility` |
| `*/migrations/*.py` | Auto-generated schema migrations — do not summarize individually | `config` |
| `*/templates/**/*.html` | Django HTML templates | `ui` |
| `*/templatetags/*.py` | Custom template filters and tags | `utility` |
| `*/management/commands/*.py` | Custom management commands (`./manage.py mycommand`) | `config`, `entry-point` |
| `wsgi.py`, `asgi.py` | WSGI/ASGI server adapter — production entry point | `config`, `entry-point` |
| `*/apps.py` | App configuration and startup hooks (`AppConfig`) | `config` |
| `*/tests.py`, `*/tests/*.py` | Unit and integration tests | `test` |
### Edge Patterns to Look For
**URL routing graph** — Create `calls` edges from `urls.py` nodes to their corresponding view nodes when `path()` or `re_path()` maps a URL pattern to a view function or class. These edges represent the HTTP routing chain.
**Signal wiring** — When `signals.py` uses `post_save.connect(handler, sender=Model)` or `@receiver(post_save, sender=Model)`, create `subscribes` edges from the signal handler function to the model class. Create `publishes` edges from the model to the signal handler to show the trigger direction.
**ORM relationships** — When `models.py` defines `ForeignKey`, `OneToOneField`, or `ManyToManyField`, create `relates_to` edges (use `depends_on` edge type) between the model classes with a description indicating the relationship type and cardinality.
**Serializer-to-model binding** — When a DRF serializer has `model = MyModel` in its `Meta` class, create a `depends_on` edge from the serializer to the model.
**View-to-serializer binding** — When a DRF ViewSet or APIView references a serializer class, create a `depends_on` edge from the view to the serializer.
### Architectural Layers for Django
Assign nodes to these layers when detected:
| Layer ID | Layer Name | What Goes Here |
|---|---|---|
| `layer:api` | API Layer | `views.py`, `serializers.py`, `urls.py`, DRF ViewSets and APIViews |
| `layer:data` | Data Layer | `models.py`, `migrations/`, database utility files |
| `layer:service` | Service Layer | `signals.py`, `tasks.py`, custom managers, service modules |
| `layer:ui` | UI Layer | `templates/`, `forms.py`, `templatetags/` |
| `layer:middleware` | Middleware Layer | `middleware.py`, `permissions.py`, authentication backends |
| `layer:config` | Config Layer | `settings.py`, `urls.py` (root), `wsgi.py`, `asgi.py`, `apps.py`, `manage.py` |
| `layer:test` | Test Layer | `tests.py`, `tests/` directory, `conftest.py` |
### Notable Patterns to Capture in languageLesson
- **Fat models vs. thin views**: Django encourages business logic in model methods, keeping views thin HTTP adapters
- **Django ORM lazy evaluation**: QuerySets are not evaluated until iterated — chain filters without DB hits
- **Class-based views (CBVs)**: Mixins like `LoginRequiredMixin`, `PermissionRequiredMixin` compose behavior through multiple inheritance
- **Signal anti-patterns**: Signals create invisible coupling; a signal in `signals.py` may be triggered by a `save()` call anywhere in the codebase
- **App isolation**: Each Django app (`INSTALLED_APPS`) should be self-contained with its own models, views, urls, and migrations
@@ -0,0 +1,109 @@
# FastAPI / Flask Framework Addendum
> Injected into file-analyzer and architecture-analyzer prompts when FastAPI or Flask is detected.
> Do NOT use as a standalone prompt — always appended to the base prompt template.
## FastAPI Project Structure
When analyzing a FastAPI project, apply these additional conventions on top of the base analysis rules.
### Canonical File Roles — FastAPI
| File / Pattern | Role | Tags |
|---|---|---|
| `main.py`, `app.py` | Application factory — creates and configures the `FastAPI()` instance | `entry-point`, `config` |
| `*/routers/*.py`, `*/api/*.py` | `APIRouter` modules — group related endpoints by domain | `api-handler`, `routing` |
| `*/schemas.py`, `*/schemas/*.py` | Pydantic request/response models | `type-definition`, `serialization` |
| `*/models.py`, `*/models/*.py` | SQLAlchemy ORM models or other DB models | `data-model` |
| `*/dependencies.py`, `*/deps.py` | `Depends()` provider functions — shared logic injected into routes | `service`, `middleware` |
| `*/crud.py`, `*/repository.py` | Database access layer — CRUD operations | `data-model`, `service` |
| `*/database.py`, `*/db.py` | DB engine, session factory, connection management | `config`, `data-model` |
| `*/config.py`, `*/settings.py` | `pydantic-settings` / `BaseSettings` config classes | `config` |
| `*/middleware.py` | Starlette middleware classes | `middleware` |
| `*/exceptions.py` | Custom exception classes and exception handlers | `utility` |
| `*/security.py`, `*/auth.py` | Auth utilities — JWT decoding, password hashing, OAuth helpers | `service`, `middleware` |
| `*/tasks.py` | Background tasks or Celery task definitions | `service`, `event-handler` |
| `*/tests/*.py`, `test_*.py` | pytest test files | `test` |
| `conftest.py` | pytest fixtures and test configuration | `test`, `config` |
### Edge Patterns to Look For — FastAPI
**Router inclusion chain** — When `app.include_router(some_router, prefix="/api")` appears in `main.py` or a router aggregator, create `imports` + `depends_on` edges from the main app file to each router module. This builds the URL hierarchy graph.
**Dependency injection tree** — When a route function or another `Depends()` provider imports and calls `Depends(some_function)`, create `depends_on` edges from the caller to the dependency provider. Trace these chains — they often span multiple files (e.g., route → auth dependency → DB session dependency).
**Pydantic model inheritance** — When a schema class inherits from another (e.g., `class UserCreate(UserBase)`), create `inherits` edges between the schema class nodes.
**ORM model relationships** — When SQLAlchemy models use `relationship()`, `ForeignKey`, create `depends_on` edges between the model classes.
**CRUD-to-model binding** — When a `crud.py` function takes a model type as an argument or directly references a model class, create `depends_on` edges from the CRUD file to the model file.
### Architectural Layers for FastAPI
| Layer ID | Layer Name | What Goes Here |
|---|---|---|
| `layer:api` | API Layer | Router files, endpoint functions with `@router.get/post/...` decorators |
| `layer:types` | Types Layer | Pydantic schema files, request/response models |
| `layer:service` | Service Layer | `dependencies.py`, `crud.py`, business logic modules |
| `layer:data` | Data Layer | ORM models, `database.py`, migrations |
| `layer:config` | Config Layer | `main.py` / `app.py` factory, `settings.py`, `config.py` |
| `layer:middleware` | Middleware Layer | `middleware.py`, `security.py`, `auth.py`, exception handlers |
| `layer:test` | Test Layer | `tests/`, `conftest.py` |
### Notable Patterns to Capture in languageLesson
- **Dependency injection as composition**: FastAPI's `Depends()` is a first-class DI system — a route can declare any number of dependencies, each of which can have their own dependencies, forming a tree resolved at request time
- **Pydantic for validation**: Request bodies, query params, and path params are automatically validated by Pydantic — invalid input raises `422 Unprocessable Entity` before your code runs
- **Async endpoints**: `async def` routes run in the event loop; `def` routes run in a threadpool — mixing them incorrectly can cause performance issues
- **Path operation order**: FastAPI matches routes in declaration order; a catch-all route before a specific one will shadow it
---
## Flask Project Structure
When analyzing a Flask project, apply these additional conventions on top of the base analysis rules.
### Canonical File Roles — Flask
| File / Pattern | Role | Tags |
|---|---|---|
| `app.py`, `__init__.py` (in app package) | Application factory (`create_app()`) or direct `Flask(__name__)` instance | `entry-point`, `config` |
| `run.py`, `wsgi.py` | Production/dev server entry point | `entry-point`, `config` |
| `*/views.py`, `*/routes.py` | Route handler functions with `@app.route` or `@blueprint.route` | `api-handler`, `routing` |
| `*/blueprints/*.py`, `*/api/*.py` | Blueprint modules — group routes by feature | `api-handler`, `routing` |
| `*/models.py` | SQLAlchemy models or other ORM models | `data-model` |
| `*/forms.py` | WTForms form classes | `validation`, `ui` |
| `*/schemas.py` | Marshmallow serialization schemas | `serialization`, `type-definition` |
| `*/config.py` | Config classes (`DevelopmentConfig`, `ProductionConfig`) | `config` |
| `*/extensions.py` | Flask extension initialization (`db = SQLAlchemy()`, `login_manager = LoginManager()`) | `config`, `singleton` |
| `*/decorators.py` | Custom route decorators (auth guards, rate limiting) | `middleware`, `utility` |
| `*/utils.py`, `*/helpers.py` | Shared utility functions | `utility` |
| `*/templates/**/*.html` | Jinja2 templates | `ui` |
| `*/static/` | CSS, JS, and asset files | `assets` |
| `*/tests/*.py`, `test_*.py` | pytest or unittest test files | `test` |
### Edge Patterns to Look For — Flask
**Blueprint registration** — When `app.register_blueprint(bp, url_prefix='/api')` appears in the application factory, create `depends_on` edges from the app factory to each blueprint module.
**Extension coupling** — When a view imports from `extensions.py` (e.g., `from .extensions import db, login_manager`), create `imports` edges to show which views depend on which extensions.
**Before/after request hooks** — When `@app.before_request` or `@blueprint.before_request` decorates a function, create `middleware` edges from those functions to the app/blueprint they attach to.
### Architectural Layers for Flask
| Layer ID | Layer Name | What Goes Here |
|---|---|---|
| `layer:api` | API Layer | Blueprint route files, view functions |
| `layer:data` | Data Layer | `models.py`, database migration files |
| `layer:service` | Service Layer | Business logic modules, `schemas.py`, service classes |
| `layer:ui` | UI Layer | `templates/`, `forms.py`, `static/` |
| `layer:config` | Config Layer | `app.py` factory, `config.py`, `extensions.py` |
| `layer:middleware` | Middleware Layer | `decorators.py`, before/after request hooks |
| `layer:test` | Test Layer | Test files, `conftest.py` |
### Notable Patterns to Capture in languageLesson
- **Application factory pattern**: `create_app()` functions allow multiple app instances (e.g., for testing) and delay extension initialization — avoids circular imports
- **Blueprint modularity**: Blueprints group related routes, templates, and static files; they are registered on the app with a URL prefix, making them independently testable
- **Flask extension protocol**: Extensions follow `init_app(app)` for lazy initialization — the extension object is created globally but bound to an app instance later
@@ -125,7 +125,10 @@ ENDJSON
After writing the script, execute it. **Use the batch index in every temp file path** — multiple file-analyzer agents run in parallel and must not overwrite each other's files:
```bash
# For Node.js scripts:
node /tmp/ua-file-extract-<batchIndex>.js /tmp/ua-file-analyzer-input-<batchIndex>.json /tmp/ua-file-extract-results-<batchIndex>.json
# For Python scripts:
python3 /tmp/ua-file-extract-<batchIndex>.py /tmp/ua-file-analyzer-input-<batchIndex>.json /tmp/ua-file-extract-results-<batchIndex>.json
```
If the script exits with a non-zero code, read stderr, diagnose the issue, fix the script, and re-run. You have up to 2 retry attempts.
@@ -166,7 +169,9 @@ Indicators from script data:
- Filename contains `.test.` or `.spec.` = `test`
- Exports a class with `Handler` or `Controller` in the name = `api-handler`
- Only type/interface exports = `type-definition`
- Named `index.ts` at a directory root with re-exports = `entry-point`
- Named `index.ts` or `index.js` at a directory root with re-exports = `entry-point` (JavaScript/TypeScript barrel)
- Named `__init__.py` at a package root with imports or re-exports = `entry-point` (Python package barrel)
- Named `manage.py` = `entry-point` (Django management script)
**Language Notes** (optional, your expert judgment):
If the structural data reveals notable language-specific patterns (e.g., many generic type parameters, decorator usage, complex trait bounds), add a brief `languageNotes` string. Only add this when genuinely educational.
@@ -81,7 +81,9 @@ Read config files (if they exist) and extract framework information:
- `tsconfig.json` -- if present, confirms TypeScript usage
- `Cargo.toml` -- if present, confirms Rust project; extract `[package].name`
- `go.mod` -- if present, confirms Go project; extract module name
- `requirements.txt` / `pyproject.toml` / `setup.py` / `Pipfile` -- if present, confirms Python project
- `requirements.txt` -- if present, confirms Python project; read line by line and match package names (strip version specifiers) against known Python frameworks: `django`, `djangorestframework`, `fastapi`, `flask`, `sqlalchemy`, `alembic`, `celery`, `pydantic`, `uvicorn`, `gunicorn`, `aiohttp`, `tornado`, `starlette`, `pytest`, `hypothesis`, `channels`
- `pyproject.toml` -- if present, confirms Python project; parse the `[project].dependencies` or `[tool.poetry.dependencies]` section and apply the same Python framework keyword matching as above. Also check for `[tool.pytest.ini_options]` (confirms pytest) and `[tool.django]` (confirms Django).
- `setup.py` / `setup.cfg` / `Pipfile` -- if present, confirms Python project; read and apply Python framework keyword matching
- `Gemfile` -- if present, confirms Ruby project
- `pom.xml` / `build.gradle` -- if present, confirms Java project
@@ -99,7 +101,8 @@ Extract from (in priority order):
1. `package.json` `name` field
2. `Cargo.toml` `[package].name`
3. `go.mod` module path (last segment)
4. Directory name of project root
4. `pyproject.toml` -- check `[project].name` first, then `[tool.poetry].name`
5. Directory name of project root
### Script Output Format
@@ -46,7 +46,7 @@ For every node, count how many other nodes it has edges pointing TO (fan-out). H
**C. Entry Point Candidates**
Identify likely entry points using these signals (score each file node, sum the scores):
- Filename matches `index.ts`, `index.js`, `main.ts`, `main.js`, `app.ts`, `app.js`, `server.ts`, `server.js`, `mod.rs`, `main.go`, `main.py`, `main.rs` -> +3 points
- Filename matches `index.ts`, `index.js`, `main.ts`, `main.js`, `app.ts`, `app.js`, `server.ts`, `server.js`, `mod.rs`, `main.go`, `main.py`, `main.rs`, `manage.py`, `app.py`, `wsgi.py`, `asgi.py`, `run.py`, `__main__.py` -> +3 points
- Node tags contain `entry-point` or `barrel` -> +2 points
- File is at the project root or one level deep (e.g., `src/index.ts`) -> +1 point
- High fan-out (top 10%) -> +1 point