Compare commits

..

No commits in common. "master" and "uebung1" have entirely different histories.

19 changed files with 1 additions and 17674 deletions

File diff suppressed because one or more lines are too long

View File

@ -1,6 +0,0 @@
def greet(name):
return f"Hello, {name} how are you doing today?"
if __name__ == "__main__":
print(greet("John"))

View File

@ -1,167 +0,0 @@
"""
Codewars Kata:
https://www.codewars.com/kata/54fe05c4762e2e3047000add
"""
class Ship:
def __init__(self, draft, crew):
self.draft = draft
self.crew = crew
def is_worth_it(self):
crew_weight = self.crew * 1.5
return self.draft - crew_weight > 20
Titanic = Ship(15, 10)
print(Titanic.is_worth_it())
"""
Codewars Kata:
https://www.codewars.com/kata/528d36d7cc451cd7e4000339
"""
class Student:
all_students = []
def __init__(self, name, fives, tens, twenties):
self.name = name
self.fives = fives
self.tens = tens
self.twenties = twenties
Student.all_students.append(self)
def total_amount(self):
return self.fives * 5 + self.tens * 10 + self.twenties * 20
richest_student = None
multiple = False
for s in Student.all_students:
if richest_student is None:
richest_student = s
elif s.total_amount() > richest_student.total_amount():
richest_student = s
multiple = False
elif s.total_amount() == richest_student.total_amount():
multiple = True
if multiple:
print("all")
else:
print(richest_student.name)
"""
Codewars Kata:
https://www.codewars.com/kata/5a03af9606d5b65ff7000009
"""
class User:
def __init__(self, name: str, balance: int, checking_account: bool):
self.name = name
self.balance = balance
self.checking_account = checking_account
def withdraw(self, amount):
if amount > self.balance:
raise ValueError("overdraw")
self.balance -= amount
return f"{self.name} has {self.balance}."
def add_cash(self, amount):
self.balance += amount
return f"{self.name} has {self.balance}."
def check(self, issuer, amount):
if amount > issuer.balance:
raise ValueError("bad check")
if not issuer.checking_account:
raise ValueError("non checking-account")
self.balance += amount
issuer.balance -= amount
return f"{self.name} has {self.balance} and {issuer.name} has {issuer.balance}."
"""
Codewars Kata:
https://www.codewars.com/kata/5941c545f5c394fef900000c
"""
class Warrior:
RANKS = [
("Greatest", 100),
("Master", 90),
("Champion", 80),
("Conqueror", 70),
("Elite", 60),
("Sage", 50),
("Veteran", 40),
("Warrior", 30),
("Fighter", 20),
("Novice", 10),
("Pushover", 1),
]
def __init__(self, level=1, rank="Pushover", experience=100, achievements=None):
self.level = level
self.rank = rank
self.experience = experience
self.achievements = achievements if achievements is not None else []
def battle(self, enemy):
if not enemy or enemy > 100:
return "Invalid level"
level_diff = enemy - self.level
rank_diff = (enemy // 10 + 1) - (self.level // 10 + 1)
if level_diff >= 5 and rank_diff >= 1:
return "You've been defeated"
else:
self.xp_won(level_diff)
if level_diff > 0:
return "An intense fight"
elif level_diff > -2:
return "A good fight"
else:
return "Easy fight"
def xp_won(self, diff: int):
xp_gained = 0
if diff == -1:
xp_gained = 5
elif diff == 0:
xp_gained = 10
elif diff > 0:
xp_gained = diff**2 * 20
if xp_gained:
self.add_xp(xp_gained)
def add_xp(self, xp_gained: int):
self.experience += xp_gained
if self.experience > 10000:
self.experience = 10000
if self.level != self.experience // 100:
self.level = self.experience // 100
for rank_name, max_level in self.RANKS:
if max_level <= self.level:
self.rank = rank_name
break
def training(self, training_arr):
description, xp_gained, min_level = training_arr
if self.level < min_level:
return "Not strong enough"
elif self.level >= min_level:
self.achievements.append(description)
self.add_xp(xp_gained)
return description

View File

@ -1 +0,0 @@
""" """

View File

@ -1,41 +0,0 @@
class Hund:
anzahl_hunde = 0
def __init__(self, name: str, rasse: str, alter: int, gewicht: float):
self.name = name
self.rasse = rasse
self.alter = alter
self.gewicht = gewicht
Hund.anzahl_hunde += 1
def __repr__(self):
return (
f"Hund(name='{self.name}', rasse='{self.rasse}',"
f"alter={self.alter}, gewicht={self.gewicht}kg"
)
def __str__(self):
return f"{self.name} ist ein {self.alter}-jähriger {self.rasse}"
def bellen(self, anzahl=1):
print("Wuff!" * anzahl)
return
def geburtstag(self):
self.alter += 1
print(
f"Alles Gute zum Geburtstag, {self.name}! Du bist jetzt {self.alter} Jahre alt."
)
return
def ist_welpe(self):
return self.alter < 2
hund1 = Hund("Bello", "Labrador", 3, 28.5)
hund2 = Hund("BBarky", "Puddel", 4, 28.5)
print(repr(hund1))
print(hund1)
print(hund1.__dict__)
print(hund1.ist_welpe())

View File

@ -1,121 +0,0 @@
from abc import ABC, abstractmethod
class Hund(ABC):
anzahl_hunde = 0
def __init__(self, name: str, alter: int, gewicht: float):
self.name = name
self.alter = alter
self.gewicht = gewicht
Hund.anzahl_hunde += 1
def __repr__(self):
return (
f"Hund(name='{self.name}', rasse='{self.rasse}',"
f"alter={self.alter}, gewicht={self.gewicht}kg"
)
def __str__(self):
return f"{self.name} ist ein {self.alter}-jähriger {self.rasse}"
@abstractmethod
def bellen(self, anzahl: int = 1) -> None:
pass
def geburtstag(self):
self.alter += 1
print(
f"Alles Gute zum Geburtstag, {self.name}! Du bist jetzt {self.alter} Jahre alt."
)
return
class Pudel(Hund):
def __init__(self, name: str, alter: int, gewicht: float):
super().__init__(name, alter, gewicht)
self.rasse = "Pudel"
self.laut = "Wauw!"
def bellen(self, anzahl: int = 1) -> None:
print(self.laut * anzahl)
return
class Labrador(Hund):
def __init__(self, name: str, alter: int, gewicht: float):
super().__init__(name, alter, gewicht)
self.rasse = "Labrador"
self.laut = "Wuff!"
def bellen(self, anzahl: int = 1) -> None:
print(self.laut * anzahl)
return
class Bulldog(Hund):
def __init___(self, name: str, alter: int, gewicht: float):
super().__init__(name, alter, gewicht)
self.rasse = "Bulldog"
self.laut = "Wuffi!"
def bellen(self, anzahl: int = 1) -> None:
print(self.laut * anzahl)
return
"""
ohne abstract method
class Hund:
anzahl_hunde = 0
def __init__ (self, name: str, alter: int, gewicht: float):
self.name = name
self.alter = alter
self.gewicht = gewicht
Hund.anzahl_hunde += 1
def __repr__(self):
return (
f"Hund(name='{self.name}', rasse='{self.rasse}',"
f"alter={self.alter}, gewicht={self.gewicht}kg"
)
def __str__(self):
return f"{self.name} ist ein {self.alter}-jähriger {self.rasse}"
def bellen(self, anzahl=1):
if not self.laut:
print("Wuff!" * anzahl)
else:
print(self.laut * anzahl)
return
def geburtstag(self):
self.alter += 1
print(
f"Alles Gute zum Geburtstag, {self.name}! Du bist jetzt {self.alter} Jahre alt."
)
return
class Pudel(Hund):
def __init__(self, name: str, alter: int, gewicht: float):
super().__init__(name, alter, gewicht)
self.rasse = "Pudel"
self.laut = "Wauw!"
class Labrador(Hund):
def __init__(self, name: str, alter: int, gewicht: float):
super().__init__(name, alter, gewicht)
self.rasse = "Labrador"
self.laut = "Wuff!"
"""
if __name__ == "__main__":
hund1 = Pudel("Bello", 1, 2)
hund2 = Labrador("Bello", 4, 3)
hund3 = Bulldog("Bello", 4, 3)
hund1.bellen(3)

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,49 +0,0 @@
import json
import logging
from pathlib import Path
logger = logging.getLogger(f"orders.{__name__}") # → "orders.load_files"
# ══════════════════════════════════════════════════════════════════════════════
# JSON-File einlesen
# ══════════════════════════════════════════════════════════════════════════════
def load_orders(path: str | Path) -> list[dict] | None:
"""
Liest eine JSON-Datei mit Bestellungen ein.
Behandelte Fehler
-----------------
UnicodeDecodeError Falsche Kodierung (z. B. Latin-1 statt UTF-8)
json.JSONDecodeError Ungültiges JSON (Syntaxfehler)
Rückgabe
--------
Liste der Bestellungen bei Erfolg, None bei Fehler.
"""
path = Path(path)
logger.info("Lese Datei: %s", path)
try:
with path.open("r", encoding="utf-8") as f:
loaded_file = json.load(f)
logger.info(f"{path} erfolgreich eingelesen")
return loaded_file
except FileNotFoundError:
logger.warning("Datei nicht gefunden: %s", path)
return None
except json.JSONDecodeError:
logger.warning(f"Konnte Datei {path} nicht decodieren")
return None
except UnicodeDecodeError as e:
logger.warning(f"Datei {path} scheint ein falsches Coding zu haben")
logger.debug(
f"UnicodeDecodeError-Details: "
f"encoding={e.encoding}, "
f"reason={e.reason}, "
f"start={e.start}, "
f"end={e.end}, "
f"bad_bytes={hex(e.object[e.start])}"
)
return None

View File

@ -1,46 +0,0 @@
"""
main.py Bestellungen einlesen und validieren
Demonstriert:
- Standard-Logging (logging-Modul) mit FileHandler + StreamHandler
- Sauberes Exception-Handling für UnicodeDecodeError & json.JSONDecodeError
- Eigene Exception-Klasse InvalidOrderError (erbt von ValueError)
"""
from pathlib import Path
from utils import setup_logger_extended
from load_files import load_orders
from validation import process_orders
def main() -> None:
logger = setup_logger_extended("orders")
# logger = setup_logger()
files = [
"orders_1_valid.json",
"orders_5_non_existing_file.json",
"orders_2_parse_error.json",
"orders_3_encoding_error.json",
"orders_4_invalid_order.json",
]
for filename in files:
BASE_DIR = Path(__file__).parent
file_path = BASE_DIR / "data" / filename
logger.info("=" * 60)
logger.info("Verarbeite: %s", filename)
orders = load_orders(file_path)
if orders is not None:
process_orders(orders)
logger.info("=" * 60)
logger.info(f"Alle {len(files)} Dateien verarbeitet. Details siehe orders.log")
if __name__ == "__main__":
main()

View File

@ -1,45 +0,0 @@
import sys
import logging
# ══════════════════════════════════════════════════════════════════════════════
# Logging-Konfiguration
# ══════════════════════════════════════════════════════════════════════════════
LOG_FORMAT = "%(asctime)s | %(levelname)-8s | %(name)-20s | %(message)s"
DATE_FORMAT = "%Y-%m-%d %H:%M:%S"
def setup_logger_extended(name: str, log_file: str = "orders.log") -> logging.Logger:
"""
Erstellt und konfiguriert einen Logger mit zwei Handlern:
- StreamHandler Ausgabe auf die Konsole (ab INFO)
- FileHandler Ausgabe in eine Log-Datei (ab DEBUG)
"""
logger = logging.getLogger(name)
logger.setLevel(logging.DEBUG) # Root-Level: alles durchlassen
# Konsole: INFO und höher
stream_handler = logging.StreamHandler(sys.stdout)
stream_handler.setLevel(logging.INFO)
stream_handler.setFormatter(logging.Formatter(LOG_FORMAT, DATE_FORMAT))
# Log-File: DEBUG und höher (detaillierter)
file_handler = logging.FileHandler(log_file, encoding="utf-8")
file_handler.setLevel(logging.DEBUG)
file_handler.setFormatter(logging.Formatter(LOG_FORMAT, DATE_FORMAT))
logger.addHandler(stream_handler)
logger.addHandler(file_handler)
return logger
def setup_logger(name: str = None, log_file: str = "orders.log") -> logging.Logger:
logging.basicConfig(
level=logging.INFO,
format="%(levelname)s %(name)s %(message)s",
)
logger = logging.getLogger(__name__)
return logger

View File

@ -1,115 +0,0 @@
import logging
logger = logging.getLogger(f"orders.{__name__}") # → "orders.validation"
# ══════════════════════════════════════════════════════════════════════════════
# Eigene Exception-Klasse
# ══════════════════════════════════════════════════════════════════════════════
class InvalidOrderError(ValueError):
"""
Wird ausgelöst, wenn eine Bestellung ungültige Geschäftsdaten enthält.
Erbt von ValueError, weil es sich um einen inhaltlichen Wertfehler handelt
(kein technisches I/O-Problem).
Attribute
---------
order_id : str
Die ID der fehlerhaften Bestellung.
field : str
Der Name des ungültigen Feldes (z. B. "qty").
value : object
Der tatsächliche (ungültige) Wert.
message : str
Lesbare Fehlerbeschreibung (auch als str(e) verfügbar).
"""
def __init__(self, order_id: str, field: str, value: object, message: str):
self.order_id = order_id
self.field = field
self.value = value
self.message = message
super().__init__(message)
def __str__(self) -> str:
return (
f"InvalidOrderError | order_id={self.order_id!r} "
f"| field={self.field!r} | value={self.value!r} "
f"| {self.message}"
)
# ══════════════════════════════════════════════════════════════════════════════
# Geschäftslogik: Validierung einer einzelnen Bestellung
# ══════════════════════════════════════════════════════════════════════════════
def validate_order(order: dict) -> None:
"""
Prüft eine einzelne Bestellung auf Plausibilität.
Wirft InvalidOrderError, sobald ein Regelverstoß entdeckt wird.
Regeln (erweiterbar):
- qty darf nicht negativ sein
- total_chf darf nicht negativ sein
- order_id und status müssen vorhanden sein
"""
order_id = order.get("order_id", "<unbekannt>")
for item in order.get("items", []):
qty = item.get("qty")
if qty is not None and qty < 0:
raise InvalidOrderError(
order_id=order_id,
field="qty",
value=qty,
message=f"Negative Menge ({qty}) ist nicht erlaubt.",
)
total = order.get("total_chf")
if total is not None and total < 0:
raise InvalidOrderError(
order_id=order_id,
field="total_chf",
value=total,
message=f"Negativer Gesamtbetrag ({total} CHF) ist nicht erlaubt.",
)
if not order.get("order_id"):
raise InvalidOrderError(
order_id="<unbekannt>",
field="order_id",
value=order.get("order_id"),
message="Pflichtfeld 'order_id' fehlt oder ist leer.",
)
# ══════════════════════════════════════════════════════════════════════════════
# Validierungs-Durchlauf über alle Bestellungen
# ══════════════════════════════════════════════════════════════════════════════
def process_orders(orders: list[dict]) -> None:
"""
Iteriert über alle Bestellungen und validiert jede einzelne.
Ungültige Bestellungen werden geloggt und übersprungen (kein Abbruch).
"""
valid_count = 0
invalid_count = 0
for order in orders.get("orders"):
try:
validate_order(order)
valid_count += 1
logger.debug("OK: %s", order.get("order_id"))
except InvalidOrderError as e:
invalid_count += 1
logger.warning(
f"Ungültige Bestellung — order_id={e.order_id}, feld={e.field}, wert={e.value}: {e.message}"
)
logger.info(
f"Validierung abgeschlossen: {valid_count} gültig, {invalid_count} ungültig."
)

View File

@ -1,5 +0,0 @@
def discount_price(price: float, percent: float) -> float:
return price - price * percent / 100
print(discount_price(100.0, 20.0))

View File

@ -1,4 +1,4 @@
from src.u1_moduleA import addition
from src.moduleA import addition
def test_a():

View File

@ -1,6 +0,0 @@
from src.u6_tests.pricing import discount_price
def test_discount_price_reduces_price():
result = discount_price(100.0, 20.0)
assert result == 80.0