Typowanie statyczne i mypy
Python jest dynamiczny, ale w ZEUS-ie traktujemy adnotacje typów jak obowiązkowy kontrakt. Typy wyłapują błędy, zanim trafią na produkcję, dokumentują API funkcji i pozwalają IDE podpowiadać sensownie. Sprawdza je mypy — w trybie strict.
Podstawowe adnotacje
def normalize_forest(name: str) -> str:
return name.strip().lower()
async def fetch_hosts(forest: str, limit: int = 100) -> list[str]:
...
Od Pythona 3.9+ używamy wbudowanych generyków (list[str], dict[str, int]),
a nie List/Dict z typing. Od 3.10+ unie zapisujemy przez |.
# starym stylem (nie używaj)
from typing import List, Optional
def f(x: Optional[int]) -> List[str]: ...
# nasz styl
def f(x: int | None) -> list[str]: ...
Optional, None i Pydantic
X | None to typ, który może być None. mypy zmusi cię do obsłużenia tego
przypadku — i o to chodzi.
def get_probe(probe_id: str) -> Probe | None:
return repo.find(probe_id)
probe = get_probe(pid)
print(probe.host) # mypy: error — probe może być None
if probe is not None:
print(probe.host) # OK — zawężenie typu (narrowing)
Typowanie funkcji asynchronicznych i ARQ
W zadaniach ARQ i handlerach FastAPI typujemy zarówno argumenty, jak i zwrot:
async def enqueue_scan(ctx: dict[str, Any], forest: str) -> int:
job = await ctx["redis"].enqueue_job("run_scan", forest)
return await job.result()
Standard ProfessNet — strict mypy
[tool.mypy]
python_version = "3.12"
strict = true
warn_unused_ignores = true
disallow_untyped_defs = true
plugins = ["pydantic.mypy"]
Standard ProfessNet: nowy kod pisze się w
strict = true. Pluginpydantic.mypyrozumie modele Pydantic i waliduje pola.
Any to dług techniczny
Any wyłącza sprawdzanie typów — używaj go świadomie i rzadko. Gdy musisz
tymczasowo wyciszyć błąd, dodaj komentarz z powodem:
data = parse(raw) # type: ignore[no-any-return] # zewn. lib bez stubów
| Konstrukcja | Kiedy |
|---|---|
| `X | None` |
Sequence[X] | argument tylko-do-odczytu (lista lub krotka) |
Protocol | kontrakt zachowania bez dziedziczenia |
TypedDict | słownik o znanych kluczach (np. payload JSON) |
Any | ostateczność, zawsze z komentarzem |
Uruchamianie
mypy app/
mypy odpalamy w CI obok ruff i black. Czerwone mypy = PR zablokowany.
Wskazówka: jeśli biblioteka nie ma typów, doinstaluj paczkę
types-...(np.types-requests) zamiast zasypywać kodtype: ignore.
Typowanie kosztuje minutę przy pisaniu, a oszczędza godziny debugowania na produkcji. W ZEUS-ie typowany, sprawdzony przez mypy kod to warunek wejścia do głównej gałęzi.