from dataclasses import dataclass
import sys

# In Python 3.14, 'copy.replace' is available.
try:
    from copy import replace 
except ImportError:
    # If on 3.13 or earlier, we simulate the manual workaround.
    def replace(obj, **changes):
        """Simulated replacement for copy.replace on older versions."""
        if not hasattr(obj, '__dict__'):
            raise TypeError("Only dataclasses or similar objects are supported by this example.")
        
        # Manually combine old attributes with new changes
        new_attrs = obj.__dict__.copy()
        new_attrs.update(changes)
        
        # Instantiate a new object manually
        return type(obj)(**new_attrs)

@dataclass(frozen=True)
class Transaction:
    id: str
    amount: float
    status: str
    timestamp: float

initial_txn = Transaction(id="TXN-001", amount=99.99, status="PENDING", timestamp=1700000000.0)

print("--- Immutability Update Comparison ---")

# ----------------------------------------------------
# Python 3.13 Workaround (Manual Re-creation)
# ----------------------------------------------------
# We need to manually extract all old fields and override 'status'
# old_attrs = initial_txn.__dict__ # Example of manual attribute access
# updated_txn_313 = Transaction(**{**old_attrs, "status": "COMPLETED"})
# This approach is verbose and less readable.
print("\n[Python 3.13]: Requires verbose manual dict unpacking or custom factory methods.")


# ----------------------------------------------------
# Python 3.14 Clean Implementation
# ----------------------------------------------------
# The standard, clean way to create a new object with one changed field
updated_txn_314 = replace(initial_txn, status="COMPLETED")

print(f"[Python 3.14 using copy.replace]:")
print(f"Original Status: {initial_txn.status}, ID: {id(initial_txn)}")
print(f"New Status:      {updated_txn_314.status}, ID: {id(updated_txn_314)}")
assert initial_txn is not updated_txn_314
print("Benefit: Clean, idiomatic creation of new immutable objects.")
