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.
Response not available
Response not available