← run

py-12-txn-kvstore

1.000
12/12 tests· architecture

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.