py-12-txn-kvstore
1.000
Proposed solution
```python
class KVStore:
def __init__(self):
# The committed store - the base level
self._store = {}
# Stack of transactions - each transaction is a dict of changes
self._transactions = []
def get(self, key):
# Look through transactions from innermost to outermost
for i in range(len(self._transactions) - 1, -1, -1):
transaction = self._transactions[i]
if key in transaction:
# If key is explicitly deleted in this transaction, return None
if transaction[key] is None:
return None
return transaction[key]
# If not found in any transaction, check the committed store
return self._store.get(key)
def set(self, key, value):
# If we have open transactions, modify the innermost one
if self._transactions:
# Get the innermost transaction
innermost = self._transactions[-1]
# Set the key in the transaction (None means delete)
innermost[key] = value
else:
# Otherwise, modify the committed store directly
self._store[key] = value
def delete(self, key):
# If we have open transactions, mark deletion in the innermost one
if self._transactions:
# Get the innermost transaction
innermost = self._transactions[-1]
# Mark as deleted (None value)
innermost[key] = None
else:
# Otherwise, delete from the committed store directly
self._store.pop(key, None)
def keys(self):
# Collect all visible keys
visible_keys = set()
# Process transactions from outer to inner to respect the order
for transaction in self._transactions:
for key, value in transaction.items():
if value is None:
# Key was deleted
visible_keys.discard(key)
else:
# Key was set or updated
visible_keys.add(key)
# Add keys from committed store that haven't been deleted
for key in self._store:
if key not in visible_keys:
# Check if this key was deleted in any transaction
deleted = False
for i in range(len(self._transactions) - 1, -1, -1):
transaction = self._transactions[i]
if key in transaction and transaction[key] is None:
deleted = True
break
if not deleted:
visible_keys.add(key)
return sorted(list(visible_keys))
def __len__(self):
return len(self.keys())
def begin(self):
# Open a new transaction - add an empty dict to the stack
self._transactions.append({})
def commit(self):
# Merge innermost transaction into its parent or committed store
if not self._transactions:
raise RuntimeError("No open transaction")
# Get the innermost transaction
innermost = self._transactions.pop()
# If there's a parent transaction, merge changes into it
if self._transactions:
parent = self._transactions[-1]
for key, value in innermost.items():
parent[key] = value
else:
# Otherwise, merge into the committed store
for key, value in innermost.items():
if value is None:
self._store.pop(key, None)
else:
self._store[key] = value
def rollback(self):
# Discard the innermost transaction
if not self._transactions:
raise RuntimeError("No open transaction")
# Simply remove the innermost transaction from the stack
self._transactions.pop()
```Test output (stdout)
............ [100%] 12 passed in 0.02s
System prompt
You are an expert programmer. Solve the task exactly as specified. Output your solution as fenced code blocks using the required file name(s) and the exact function/type signatures requested. Prefer correctness; do not include prose outside code unless asked.