Kódminőség
A Python service-ben számos eszközt alkalmazunk, hogy a kódminőség magas szintű és konzisztens legyen. Az oldal ezen eszközök leírását, illetve a beállításukhoz és konfigurációjukhoz szükséges információkat tartalmazza.
Általánosan elmondható, hogy az adott eszközök konfigurációs beállítása a pyproject.toml fájl megfelelő tábláiban találhatók. Ezek szerkesztésénél ügyeljük arra, hogy a fájl átlátható maradjon, ne szóródjanak szét azonos egységhez tartozó táblák.
Több eszköz fut merge request-eknél is, azaz a rossz kódminőség képes gátolni a merge-elhetőséget. Az eszközöket, melyekre ez fennáll, a ikonnal jelezzük, illetve az alábbi összefoglaló táblázat is mutatja.
| Eszköz | Funkció | Ellenőrzött? |
|---|---|---|
| Black | Kódformázás | |
| Ruff | Linter, logikai és minőségbeli javítások | |
| Pyright | Típusellenőrzés | |
| Deptry | Függőséghasználat ellenőrzése |
Beépített hibajelzések JetBrains IDE-kben
A JetBrains IDE-knek (PyCharm, IntelliJ) van saját kódformátum, linting és type checking megoldásuk is. Ez alapvetően nem probléma, ugyanakkor zavaró lehet, hogy ugyanazt a hibát több dolog is jelzi, illetve a beépített linter és type-checker többször jelez olyan dolgokat, amik valójában nem állnak fenn. Emellett a kódformátum nincs bekonfigurálva, hogy egyezzen a megoldásunkkal.
A beépített eszközöket a beállításokban a következő helyeken tudjuk konfigurálni:
Editor→Code Sytle→PythonEditor→Inpsections→ Keresés:Python
JetBrains IDE verziók
Korábbi IntelliJ verzióknál számos beállítás nem létezik, melyeket az integrációknál leírunk, ugyanis a plugin-eknek nem lehet a legfrissebb verzióját letölteni. Emiatt érdemes mindig a legfrissebb IntelliJ verziót telepíteni. Ez PyCharm-ra is fennáll.
Formázás – Black 
Egységes kódformátum biztosítására a Black formázót használjuk. A teljes kódbázis formázását a következő parancs segítségével tehetjük meg:
Emellett használhatjuk a pixi run check-format parancsot is, ez kizárólag ellenőrzi a kódformátumot, de nem javítja azokat.
Almappa ellenőrzése
Ha kizárólag egy almappát vagy egy fájlt akarunk ellenőrizni, az megtehetjük a pixi run black <útvonal> parancs kiadásával. A check-format parancs is ezt alias-olja.
Felsorolásvégi vessző
A Black formázó tiszteletben tartja a felsorolásvégi záró vesszőt, amit azt jelenti, hogy a
alakú kódot nem fogja átalakítani
alakúvá. Ez nem áll fenn, ha ezt lehagyjuk. Így tehát ügyeljünk arra, hogy ha a sorok tördelését meg akarjuk tartani például lista, dictionary vagy függvénydefiníciók esetén, akkor ne felejtsük el a felsorolásvégi vesszőt.
Linting – Ruff 
Általános kódminőség fenntartására a Ruff linter-t alkalmazzuk. Ez segít abban, hogy elkerüljünk gyakori formai és logikai hibákat, inkonzisztenciákat, illetve modern kódhasználatot kényszerít.
A teljes kódbázis ellenőrzését a következő parancs segítségével tehetjük meg:
Amennyiben a parancs után elérési utat specifikálunk, az adott mappa tartalmát tudjuk ellenőrizni. Az automatikusan javítható hibákat a pixi run lint-autofix parancs segítségével javíthatjuk.
A Ruff-nak van a nagyobb IDE-kben integrációja, ami mutatja a hibák helyét, illetve leírást hozzájuk. Most részletezzük a beállítási folyamatot.
Navigáljunk el a Plugin marketplace-re (Settings > Plugins > Marketplace) és telepítsük a Ruff nevű plugint.
Note
Feltétele a Ruff futásának, hogy a JetBrains IDE megtalálja a ruff csomagot a környezetben. Mindenesetre ez a függőségek része.
Tippek type hintek javítására
A type-hintek meghatározásában segíthet, ha alkalmazunk valami olyan plugin-t, ami mutat inlay hint-eket. Erre egy lehetséges segítség JetBrains IDE-ben a Python Inlay Params plugin, ami automatikusan mutatja függvények return típusát, amennyiben sikerül azt kitalálnia.
VS Code-ban van beépítve hasonló funkcionalitás, a következő beállításokat kell bekapcsolni hozzá:
Tippek függvénykomplexitási hibák javítására
A ruff-ban vannak különböző kód komplexitás mértékek. Ezek főleg azon alapszanak, hogy hány és mennyire mély if-else-ekben gondolkodik a kód (illetve loop, try, stb…). Ha adott függvényben nagyon sok a szétválasztás, arra linter hibát kapunk.
Ezt több módon lehet kezelni. Rengetegszer előfordul, hogy egy kisebb-nagyobb if-else-ben valójában egyetlen változónak a konvertálását végezzük. Ekkor ezt pl. kivezethetjük egy ‘_convert_x_variable_to_y’ jellegű függvénybe.
Másik ilyen jellegű eset lehet egy hiba elkapás és dobás valami váratlan esetben adott állapotban. (Pl. két listának ugyanolyan hosszúnak kéne lennie, de mégse azok, stb…) Ekkor ezt az ellenőrzést kivezethetjük egy _assert_x_is_good(x) -> None függvénybe, ami ha minden jó, nem csinál semmit, ha pedig valami nem okés, akkor dob egy hibát.
Egyéb esetek közé tartozik, hogy ha a függvényünk jól definiált lépésekből áll úgy, hogy a lépéseken belül csak olyan dolgokat számolunk, amik később nem kellenek (a kimeneten kívül), akkor ezeket is függvényekké alakíthatjuk.
Persze van, hogy egy komplex függvényt így sem lehet egyszerűbbé tenni, ekkor akár ignorálni is lehet a hibát.
Hibák ignorálása
Alapvetően minden hiba ellenőrzése be van kapcsolva, néhány kivétellel (lásd pyproject.toml). Ehhez indokolt esetben lehet kivételt hozzávenni. Ugyanakkor globális szinten ne ignoráljunk olyan hibát, ami máshol problémákhoz vagy kódminőség romláshoz vezethet (pl. exception catching figyelmeztetések). Emellett globális ilyenkor írjunk egy indoklást, hogy miért vettük fel a globális ignore-ok közé.
Ignorált hibák
| Hibakód | Indok |
|---|---|
| ASD123 | BSD123 |
Esetenkénti alapon lehet, sőt, néha kell is hibákat ignorálni. Ennek klasszikus példája, hogy ha valami failsafe függvényt gyártunk. Ekkor ugyanis bármilyen exception-t el akarunk kapni, viszont erre a linter hibát dob. Nyilván ekkor a hiba ignorálható, mivel a függvény explicit célja a bare except használat.
További példák közé tartozik a már korábban említett „megoldhatatlan komplexitás“ problémája, illetve esetenként a dunder method docstring-ek sem túl indokoltak.
Ignorálni a hibát az adott sor végére írt # noqa: <hibakód> vagy # noqa: <hibakód1>, <hibakód2>[, ...] kommenttel lehet. Fájl szinten is lehet ignorálni adott hiba összes megjelenését. Ehhez a fájl elejére kell beilleszteni a # ruff: noqa: <hibakód> kommentet.
Type checker – Pyright
Formázás és kódminőség ellenőrzés mellett célszerű egy statikus típusellenőrző használata is, hiszen ezzel számos hibát azok bekövetkezése előtt le tudunk kezelni.
Több statikus típusellenőrző van Python-hoz, ezek közül a kettő legnagyobb a MyPy illetve a Pyright. A Pyright jobban követi a PEP-et, illetve beépített opció VS Code-ban, így most ennek a beállítását részletezzük.
Astral ty
A Ruff készítőinél jelenleg folyamatban van egy type checker gyártása, ami a ty névre hallgat. Jelenleg ez még nagyon alpha fázisban van, ugyanakkor érdemes követni a fejlődését, mert lehet, versenyképes alternatíva lesz a Pyright-ra.
Navigáljunk el a Plugin marketplace-re (Settings > Plugins > Marketplace) és telepítsük a Pyright, illetve LSP4IJ nevű plugin-eket. Ezután a Tools → Pyright → Project beállítások írjuk felül a következőket:
Executable: az útvonalat megadja apixi run which pyrightparancsConfiguration file:<python-service mappa>/pyproject.tomlLanguage server executable: az útvonalat megadja apixi run which python-langserverparancsRunning mode:LSP4IJ- Kapcsoljuk be a
Prefix tooltip messages with "Pyright:"beállítást (opcionális)

A Pyright szerves részét képezi a Pylance bővítménynek, elegendő ezt telepíteni.
Pyright verzió a Pylance-ben
Mivel a Pylance saját Pyright-ot tart fenn, és nem az interpreterből táplálkozik, Python konfigurációtól kívülállóan kell felüldefiniálnunk a Pyright verziót, ha azt akarjuk, hogy ugyanaz a verzió fusson, ami a lock file-ban szerepel. Szerencsére ez lehetséges a kövektező beállítással
Változtatásnál ügyelnünk kell arra, hogy mind a .vscode/settings.default.json fájlban, mind a függőségek között frissítsük a verziót.
Végül ha egy type checker-t bekapcsolunk, az bár általában hasznos, előfordul, hogy saját limitációi, külső programcsomagok mistype-olása, vagy esetleg kódstruktúrálási (pl. hibát dobó validációs függvények) okok miatt nem lehet hiba nélkül type-hintelni. Ekkor ha biztosak vagyunk benne, hogy indokolt, a type hibákat is lehet ignorálni, Pyright esetén a # pyright: ignore[<hibanév>] sorvégi kommenttel.
Univerzális hibaignorálás
A # type: ignore komment a PEP 484-ben került bevezetésre, azaz a Python specifikáció része, és így az összes type checker támogatja. Hátránya, hogy minden hibát figyelmen kívül hagy, azaz ha véletlen egy ismert hiba közvetlen közelében előjönne egy új type hiba, akkor azt a # type: ignore szintén ignorálja.
Helyette célszerű a # pyright: ignore[<hibanév>] flag-et alkalmazni, mivel ez hibaspecifikus, így sokkal kisebb valószínűséggel fed el egyéb hibákat.
Függőséghasználat – Deptry
Fontos, hogy függőségek, amiket a kódban használunk, és azok, melyeket a projekt definiál, azok összhangban legyenek. Ellenkező esetben előfordulhat, hogy egy modult kizárólag azért érünk el, mert egy másik csomaghoz szükséges, és akár egy verziófrissítéssel eltűnhet a telepített dependenciák közül.
Erre a problémára ad megoldást a Deptry, ami összeveti a pyproject.toml-ben definiált függőségeket a kódbázis által használtakkal. Funkciói a következők:
- Jelenti a hiányzó függőségeket (
DEP001) - Megtalálja a nem használt függőségeket (
DEP002) - Felderíti a tranzitív (azaz egyéb csomag függőségei alapján telepített) függőségeket (
DEP003)
A teljes projekt ellenőrzését a következő paranccsal tehetjük meg
Hibák ignorálása
Itt nem feltétlen tudunk vagy értelmes minden hibát kezelni, sőt, előfordulhat, hogy valójában szükséges függőséghasználatra kapunk hibát. Erre példa a torch könyvtár definiálása, amit expliciten nem használ a kód, ezért DEP002 hibakódot kap, ugyanakkor a torch esetén verzióról verzióra változik a működés, ezért sokszor el szeretnénk kerülni, hogy egy dependency resolution folyamat határozza meg, mi kerül végül feltelepítésre.
Így tehát – bár törekedve arra, hogy adott függőség pontosan akkor legyen definiálva, ha használt is – eltérhetünk attól, hogy minden vizsgálva legyen.
Hibákat ignorálni a pyproject.toml-ben lehet, itt még nincs lehetőség kommentek segítségével megtenni ezt.