Task_9: PoiType als StrEnum

This commit is contained in:
Marco Schmid 2026-05-12 16:52:55 +02:00
parent 0ba947861f
commit 24a7051632
3 changed files with 34 additions and 50 deletions

52
TASK.md
View File

@ -1,35 +1,41 @@
# Task 8 — Python Package
# Task 9 — PoiType als StrEnum
## Rückblick Task 7: Logging
## Rückblick Task 8: Python Package
Ihr habt alle `print()`-Aufrufe durch das `logging`-Modul ersetzt. Warum ist das besser?
Ihr habt das Projekt in ein Python-Package umgewandelt. Die wichtigsten Punkte:
- **Log-Level steuern ohne Code-Änderung:** Mit `logging.basicConfig(level=logging.DEBUG)`
sieht man alle Details, mit `level=logging.WARNING` nur Probleme — ohne eine einzige
Zeile im Anwendungscode anzufassen.
- **`logger = logging.getLogger(__name__)`:** Jedes Modul bekommt seinen eigenen Logger,
benannt nach dem Modul. Im Output sieht man sofort, *woher* eine Meldung kommt.
- **`logging.basicConfig()` gehört in `main.py`** (den Einstiegspunkt), nicht in
Hilfmodule — sonst konfiguriert jedes importierte Modul eigenständig das Logging,
was zu unvorhersehbarem Verhalten führt.
- **Alternative:** Für grössere Projekte lohnt sich eine separate Logging-Konfiguration
via `logging.config.dictConfig()` oder eine externe Library wie `loguru`.
- **Modul vs. Package:** Ein einzelnes `.py`-File ist ein Modul. Ein Ordner mit
`__init__.py` ist ein Package — er kann mehrere Module bündeln und nach aussen
eine saubere API exponieren.
- **Relative Imports** (`from .models import POI`): Beziehen sich auf das eigene
Package, sind refactoring-sicher und machen klar, dass etwas intern ist.
Absolute Imports (`from overpass_project.models import POI`) funktionieren auch,
sind aber abhängig vom Paketnamen.
- **`from overpass import *`** ist problematisch, weil unklar ist, welche Namen
importiert werden — das kann zu Namenskollisionen führen und erschwert das Lesen
des Codes stark.
## Aufgabe
Das Projekt besteht aktuell aus losen Modulen (`main.py`, `models.py`, `overpass.py`).
Ziel ist es, daraus ein sauberes Python-Package zu machen.
In `main.py` steht aktuell:
```python
poi_type = "bergbahn"
```
Das ist ein sogenannter **Magic String** — ein roher String, dem man nicht ansieht,
welche Werte gültig sind, und der nirgends geprüft wird.
**Konkret:**
1. Lege eine leere `__init__.py` im Projektordner an.
2. Benenne `overpass.py` in `fetcher.py` um (um später Namenskonflikte zu vermeiden).
3. Passe alle Imports in `main.py` und `fetcher.py` auf **relative Imports** um
(`from .models import …` statt `from models import …`).
1. Füge in `models.py` eine `PoiType`-Klasse hinzu, die von `StrEnum` erbt,
mit den Werten `BERGBAHN` und `RESTAURANT`.
2. Ersetze in `main.py` den String `"bergbahn"` durch `PoiType.BERGBAHN`.
3. Passe den Import in `main.py` entsprechend an.
**Fragen zum Nachdenken:**
- Was ist der Unterschied zwischen einem Modul und einem Package in Python?
- Was bewirkt `__init__.py` — was passiert ohne sie?
- Wann verwendet man relative Imports, wann absolute?
- Warum ist `from overpass import *` problematisch?
- Was ist der Unterschied zwischen `Enum` und `StrEnum`?
- Warum ist `PoiType.BERGBAHN` besser als der String `"bergbahn"`?
- Was passiert, wenn jemand `PoiType("bergbahn")` schreibt — funktioniert das?
- Wo könnte ein Enum an seine Grenzen stossen?

View File

@ -1,7 +1,6 @@
import requests
from pprint import pprint
from models import POI
import logging
import requests
from models import POI
logger = logging.getLogger(__name__)
@ -126,25 +125,4 @@ def _parse_pois(raw: dict, poi_type: str) -> list[POI]:
pois.append(_parse_poi(data=element, poi_type=poi_type))
except OverpassApiError as exc:
logger.warning(f"POI übersprungen (id={element.get('id', '?')}): {exc}")
return pois
if __name__ == "__main__":
BERGBAHN_QUERY = """
[out:json][timeout:2][maxsize:500000];
(
node["aerialway"="station"]({bbox});
way["aerialway"="station"]({bbox});
node["railway"="funicular"]({bbox});
way["railway"="funicular"]({bbox});
node["railway"="station"]["funicular"="yes"]({bbox});
);
out center body;
"""
bbox = (46.72, 9.70, 46.92, 10.00)
# bbox = (45.8, 5.9, 47.8, 10.5)
result = load_pois(overpass_query=BERGBAHN_QUERY, bbox=bbox)
pprint(result)
return pois

View File

@ -1,6 +1,6 @@
import logging
from overpass import load_pois, OverpassApiError
from models import POI
from .fetcher import load_pois, OverpassApiError
from .models import POI
logging.basicConfig(
level=logging.INFO,