Test

Prompt

Schreibe in Python 3.11 (nur Standardbibliothek) eine Datei `kvstore.py` mit einem threadsicheren In-Memory-Key-Value-Store. Halte dich EXAKT an diese API – sie wird mit einer versteckten Testsuite geprüft. Keine Platzhalter, keine TODOs. Modulebene: Exceptions NoTransactionError, ConflictError, SnapshotError (erben von Exception). class KVStore: def __init__(self, clock: Callable[[], float] = time.monotonic) Alle Zeitberechnungen nutzen ausschließlich self.clock(). 1. set(key: str, value: Any, ttl: float | None = None) -> None - ttl in Sekunden ab clock() beim Aufruf; ttl <= 0 -> ValueError. - Ohne ttl läuft der Key nie ab; set ohne ttl entfernt eine bestehende TTL. 2. get(key) -> Any | None - Ein Key ist abgelaufen, wenn clock() >= Ablaufzeit. Abgelaufene Keys verhalten sich in ALLEN Methoden so, als existierten sie nicht. 3. delete(key) -> bool (True nur, wenn der Key existierte und nicht abgelaufen war) 4. incr(key, by: int = 1) -> int - Fehlender Key startet bei 0. Ist der Wert kein int (bool zählt NICHT als int) -> TypeError, Store bleibt unverändert. Eine bestehende TTL bleibt erhalten. 5. count(value) -> int - Anzahl lebender Keys, deren Wert == value ist. Werte dürfen unhashbar sein. 6. keys(pattern: str = "*") -> list[str] - Aufsteigend sortiert. Glob: `*` = beliebig viele Zeichen (auch 0), `?` = genau ein Zeichen, alle anderen Zeichen wörtlich (auch [ ] \). Ohne fnmatch, glob, re. 7. Transaktionen: begin(), commit(), rollback() – jeder Thread hat seinen eigenen Stack. - Beliebig tief verschachtelbar. Inneres commit übernimmt die Änderungen in die nächstäußere Ebene; inneres rollback verwirft nur die innerste Ebene. - commit/rollback ohne offene Transaktion -> NoTransactionError. - Ein Thread sieht in seiner Transaktion seine eigenen Änderungen (inkl. count/keys). - Für andere Threads werden Änderungen erst beim äußersten commit sichtbar, atomar (alles oder nichts). - Optimistische Konflikterkennung: Wurde seit dem äußersten begin() von einem anderen Thread ein Key geändert, den diese Transaktion gelesen oder geschrieben hat, wirft das äußerste commit ConflictError, die gesamte Transaktion wird verworfen und der Stack ist danach leer. * Lesen/Schreiben: get, set, delete, incr betreffen ihren Key. count() und keys() gelten als Lesen ALLER Keys. * Schreiboperationen ohne Transaktion gelten als sofort committet. * TTL-Ablauf ist keine Änderung. 8. snapshot() -> int / restore(snapshot_id: int) -> None - snapshot speichert den aktuell COMMITTETEN Zustand inkl. Ablaufzeiten (nicht die Transaktionssicht). IDs fortlaufend ab 1. - restore stellt ihn wieder her. Unbekannte ID -> SnapshotError. Aufruf, während der aufrufende Thread eine offene Transaktion hat -> SnapshotError. - restore gilt für die Konflikterkennung als Änderung aller Keys. - Werte werden nirgends kopiert (kein deepcopy). 9. Beliebig viele Threads gleichzeitig: keine Race Conditions, keine Deadlocks. Ausgabe: nur der vollständige Code, danach maximal 5 Sätze zu getroffenen Annahmen.

Drag to resize

Response not available

Drag to resize

Response not available

Drag to resize
Drag to resize
Drag to resize