146 lines
5.3 KiB
Markdown
146 lines
5.3 KiB
Markdown
|
|
# Phase 7 Quality Review – 07b: Type-Check (mypy)
|
|||
|
|
|
|||
|
|
> **Projekt:** CRM-System (`/a0/.a0/crm-system/`)
|
|||
|
|
> **Tool:** mypy v2.1.0 (mit `--ignore-missing-imports`)
|
|||
|
|
> **Datum:** 2026-06-04 02:28 UTC
|
|||
|
|
> **Status:** ⚠️ WARN – 137 Fehler in 32 Dateien (53 geprüft)
|
|||
|
|
|
|||
|
|
## Zusammenfassung
|
|||
|
|
|
|||
|
|
| Metrik | Wert |
|
|||
|
|
|---|---|
|
|||
|
|
| Geprüfte Quell-Dateien | 53 |
|
|||
|
|
| Dateien mit Fehlern | 32 |
|
|||
|
|
| Total mypy Errors | 137 |
|
|||
|
|
| Kritische Typ-Fehler (Bugs) | 3 |
|
|||
|
|
| Style/Pattern-Fehler | 134 |
|
|||
|
|
|
|||
|
|
## Fehler-Kategorien und Analyse
|
|||
|
|
|
|||
|
|
### 1. `Class cannot subclass "BaseModel"` / `DeclarativeBase` / `BaseSettings` – 28x
|
|||
|
|
**Schweregrad:** Warning
|
|||
|
|
|
|||
|
|
Diese Fehler treten in allen Pydantic-Schema-Files und SQLAlchemy-Base-Klassen auf. Sie sind **KEIN Bug**, sondern ein mypy-Konfigurationsproblem:
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
app/schemas/account.py:13: error: Class cannot subclass "BaseModel" (has type "Any")
|
|||
|
|
app/core/config.py:17: error: Class cannot subclass "BaseSettings" (has type "Any")
|
|||
|
|
app/core/db.py:22: error: Class cannot subclass "DeclarativeBase" (has type "Any")
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**Root Cause:** Pydantic v2 und SQLAlchemy 2.0 liefern nicht in allen Installationen vollständige Type-Stubs. mypy kann den konkreten Typ von `BaseModel`/`BaseSettings`/`DeclarativeBase` nicht auflösen.
|
|||
|
|
|
|||
|
|
**Fix:**
|
|||
|
|
- `pip install pydantic[mypy]` für Pydantic-Plugin
|
|||
|
|
- `mypy.ini` / `pyproject.toml` anpassen:
|
|||
|
|
```ini
|
|||
|
|
[tool.mypy]
|
|||
|
|
plugins = ["pydantic.mypy"]
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**Empfehlung:** Kein Blocker für v1.0-Deployment. In v1.1 beheben.
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
### 2. `Untyped decorator makes function ... untyped` – 50x
|
|||
|
|
**Schweregrad:** Style
|
|||
|
|
|
|||
|
|
Jeder FastAPI-Router mit `@router.get(...)` / `@router.post(...)` erzeugt diesen Fehler:
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
app/api/v1/auth.py:26: error: Untyped decorator makes function "register" untyped
|
|||
|
|
app/api/v1/deals.py:45: error: Untyped decorator makes function "create_deal" untyped
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**Root Cause:** FastAPI-Decorators haben keine präzisen Type-Hints in den Stubs, die mypy lesen kann.
|
|||
|
|
|
|||
|
|
**Fix:**
|
|||
|
|
```python
|
|||
|
|
# Expliziten Return-Type annotieren:
|
|||
|
|
@router.post("/register", response_model=UserOut, status_code=201)
|
|||
|
|
async def register(...) -> UserOut: # ← Return-Type hinzufügen
|
|||
|
|
...
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**Empfehlung:** Kein Blocker. 50 Stellen manuell zu annotieren ist aufwändig, aber nicht funktional kritisch.
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
### 3. `Returning Any from function declared to return ...` (no-any-return) – 20x
|
|||
|
|
**Schweregrad:** Warning
|
|||
|
|
|
|||
|
|
Betrifft Service-Layer und einige Router:
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
app/core/security.py:28: error: Returning Any from function declared to return "str"
|
|||
|
|
app/services/account_service.py:44: error: Returning Any from function declared to return "Account | None"
|
|||
|
|
app/core/deps.py:53: error: Returning Any from function declared to return "User"
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**Root Cause:** ORM-Ergebnisse (`await session.execute()`) liefern `Any` zurück, wenn das Result nicht explizit typisiert wird.
|
|||
|
|
|
|||
|
|
**Fix (Beispiel):**
|
|||
|
|
```python
|
|||
|
|
# Statt:
|
|||
|
|
result = await session.execute(query)
|
|||
|
|
return result.scalar_one_or_none() # mypy sagt: Any
|
|||
|
|
|
|||
|
|
# Besser:
|
|||
|
|
result = await session.execute(query)
|
|||
|
|
user: User | None = result.scalar_one_or_none()
|
|||
|
|
return user
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**Empfehlung:** Kein Blocker, aber die Services und `deps.py` sollten mittelfristig nachgebessert werden. Besonders kritisch ist `deps.py:53` (`get_current_user → User`), weil hier ein Any-Wert durch das Dependency-System fließt.
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
### 4. `Unused "type: ignore" comment` – 5x
|
|||
|
|
**Schweregrad:** Info
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
app/core/config.py:86: error: Unused "type: ignore" comment
|
|||
|
|
app/services/deal_service.py:30: error: Unused "type: ignore" comment
|
|||
|
|
app/api/v1/dashboard.py:30: error: Unused "type: ignore" comment
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**Fix:** `# type: ignore[code]` entfernen wo nicht mehr nötig, oder korrekten Error-Code ergänzen.
|
|||
|
|
|
|||
|
|
**Empfehlung:** Einfaches Cleanup vor v1.1.
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
### 5. Funktionale Type-Fehler (Bug-verdächtig) – 3x ⚠️
|
|||
|
|
|
|||
|
|
**a) `app/services/contact_service.py:44` – Inkompatibler Argument-Typ**
|
|||
|
|
```
|
|||
|
|
app/services/contact_service.py:44: error: Argument 2 to "_validate_account" has incompatible type "int | None"; expected "int"
|
|||
|
|
```
|
|||
|
|
→ **Risiko:** `account_id` kann `None` sein, aber `_validate_account` erwartet `int`. **MUSS gefixt werden.**
|
|||
|
|
|
|||
|
|
**b) `app/services/activity_service.py:106` – `None` hat kein Attribut `value`**
|
|||
|
|
```
|
|||
|
|
app/services/activity_service.py:106: error: Item "None" of "ActivityType | None" has no attribute "value"
|
|||
|
|
```
|
|||
|
|
→ **Risiko:** `ActivityType` kann `None` sein, aber die `enum.value` Property wird trotzdem aufgerufen. **MUSS gefixt werden.**
|
|||
|
|
|
|||
|
|
**c) `app/api/v1/deals.py:106-107` – Typ-Inkompatibilität bei Pipeline-Kalkulation**
|
|||
|
|
```
|
|||
|
|
app/api/v1/deals.py:106: error: No overload variant of "int" matches argument type "object"
|
|||
|
|
app/api/v1/deals.py:107: error: Argument 1 to "float" has incompatible type "object"; expected "str | Buffer | SupportsFloat | SupportsIndex"
|
|||
|
|
```
|
|||
|
|
→ **Risiko:** Pipeline-Wert-Berechnung nutzt unvalidierte Daten aus der DB. **Potential für 500-Fehler bei unerwarteten DB-Werten.**
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## Empfehlung
|
|||
|
|
|
|||
|
|
**GO für Phase 8 mit Auflagen.** Die 3 funktionalen Type-Fehler MÜSSEN vor dem Deployment gefixt werden:
|
|||
|
|
1. `contact_service.py:44` – `account_id`-None-Check
|
|||
|
|
2. `activity_service.py:106` – `ActivityType`-None-Check
|
|||
|
|
3. `deals.py:106-107` – Pipeline-Calculation-Type-Guard
|
|||
|
|
|
|||
|
|
Die restlichen 134 Fehler sind Non-Blocker (Style/Konfiguration/Stubs). Sie sind typisch für FastAPI+SQLAlchemy-Projekte unter mypy und sollten sukzessive in v1.1 bereinigt werden.
|
|||
|
|
|
|||
|
|
**Priorität für Phase 8:** Fix der 3 funktionalen Typ-Fehler → dann Deployment.
|