# Python-Projekt

## Python-Spezifika

- Python 3.10+ (native type hints: X | None, list[X])
- PEP 8 (Style), PEP 484 (Type Hints), PEP 257 (Docstrings)
- Type Hints: vollständig, keine typing.Any ohne Begründung

## Paketmanager & Tooling

- **uv** für Dependencies (seit 2025-11, ersetzt poetry)
- example_*.py Dateien bei Schnittstellenänderungen aktualisieren
- Wichtige uv Commands:
  - `uv sync` - Dependencies installieren
  - `uv sync --all-groups` - Mit allen Dev-Dependencies
  - `uv add <package>` - Package hinzufügen
  - `uv run <command>` - Command in venv ausführen

## Dokumentation

- Docstrings: Google-Style (Args/Returns/Raises/Examples)
- Code-Blöcke mit ` ```python`
- Deutsch erlaubt
- **MkDocs:** Nur aus Docstrings generieren, kein Extra-Content (außer Getting Started)

## Error Handling

- Spezifische Exceptions (ValueError, TypeError, etc.)
- **Niemals** bare `except:` oder `except Exception:` ohne Begründung
- Bei externen Aufrufen: spezifische Fehler wrappen (z.B. `requests.RequestException → APIError`)

---

## Kritische Constraints

- NICHT modifizieren: dyno.sdl, dynamic.sdl, swagger.json - Schemas niemals brechen
- Client-API Breaking Changes erlaubt (PoC-Status)
- Bei API-Änderungen: example_*.py synchron halten
- Imports: absolute aus src/questra_data

## Type System

**GraphQL Schema → Python Types:**

- `LongNumberString` (IDs): GraphQL serialisiert als **String**, Python Type Hints: `str`
  - Grund: JavaScript/JSON keine 64-bit Integers sicher unterstützen
  - `_id`, `_rowVersion`, `timeseries_id` etc. sind **immer String**
- Numerische Werte (TimeSeries-Values, Properties): Python `int`, `float` oder `Decimal`
- GraphQL Mutation-Inputs vs. Query-Outputs:
  - **Input** (Mutation): `enableQuotation`, `enableAudit` (Verb-Form, Kommando)
  - **Output** (Query): `quotationEnabled`, `auditEnabled` (Adjektiv-Form, Zustand)

```python
# ✅ Korrekte Type Hints
def list_items() -> list[dict[str, Any]]:  # IDs als String
    pass

def list_quotation_values() -> dict[str, dict]:  # Item-IDs als String
    pass

# ❌ Falsch
def list_items() -> list[dict[int, Any]]:  # IDs sind KEINE ints!
    pass
```

## API-Verhalten

**create_items()/update_items() Rückgabe:** Nur `_id`, `_rowVersion`, `_existed` - KEINE Properties!

```python
# ✅ Pattern: Original-Daten mit IDs kombinieren
for original, created in zip(items, created_items):
    original["_id"] = created["_id"]
    original["_rowVersion"] = created["_rowVersion"]
```

**Relationen:**

- `parentNamespaceName` ist **Pflicht** bei InventoryRelation
- **1:n** - Items erstellen: `_{propertyName}Id` (z.B. `_authorId`)
- **n:m** - Update von **Child-Seite**: `update(Hashtags)` mit `posts: [id1, id2]`

```python
# 1:n - Item erstellen
{"content": "...", "_authorId": 123}

# n:m - Update von Child-Seite (Hashtags)
{"_id": 1, "_rowVersion": 1, "posts": [10, 20]}  # Direkt IDs als Array!
```

## Dokumentation (Projekt-spezifisch)

Quotation in Dokumentation zu **Notierung** übersetzen
