Deep Difference and Search of any Python object/data with delta and hash capabilities.
—
Store differences as delta objects and apply them to create new objects or modify existing ones. Delta provides a powerful system for capturing, serializing, and applying changes between objects, enabling version control-like functionality and patch operations for Python data structures.
Create delta objects from DeepDiff results and manage their lifecycle with various configuration options.
class Delta:
def __init__(
self,
diff: Union[DeepDiff, Mapping, str, bytes, None] = None,
delta_path: Optional[str] = None,
delta_file: Optional[IO] = None,
delta_diff: Optional[dict] = None,
flat_dict_list: Optional[List[Dict]] = None,
flat_rows_list: Optional[List[FlatDeltaRow]] = None,
deserializer: Callable = pickle_load,
log_errors: bool = True,
mutate: bool = False,
raise_errors: bool = False,
safe_to_import: Optional[Set[str]] = None,
serializer: Callable = pickle_dump,
verify_symmetry: Optional[bool] = None,
bidirectional: bool = False,
always_include_values: bool = False,
iterable_compare_func_was_used: Optional[bool] = None,
force: bool = False,
fill: Any = not_found
):
"""
Create a Delta object from a DeepDiff result or other sources.
Parameters:
- diff: DeepDiff object, dictionary, or serialized difference data
- delta_path: Path to delta file to load
- delta_file: File object containing delta data
- delta_diff: Dictionary containing diff data
- flat_dict_list: List of flat dictionaries for delta creation
- flat_rows_list: List of flat row objects for delta creation
- deserializer: Function to deserialize delta data
- log_errors: Whether to log errors during delta operations
- mutate: Whether to mutate the original object when applying delta
- raise_errors: Whether to raise errors instead of logging them
- safe_to_import: Set of modules that are safe to import during deserialization
- serializer: Function to serialize delta data
- verify_symmetry: Whether to verify symmetry of bidirectional deltas
- bidirectional: Whether delta can be applied in both directions
- always_include_values: Whether to always include values in delta
- iterable_compare_func_was_used: Whether custom iterable comparison was used
- force: Force delta creation even with warnings
- fill: Fill value for missing items
"""Serialize delta objects to various formats for storage, transmission, and persistence.
def dump(self, file) -> None:
"""
Serialize delta to a file object.
Parameters:
- file: File object to write delta to
"""
def dumps(self) -> bytes:
"""
Serialize delta to bytes.
Returns:
Bytes representation of the serialized delta.
"""
def to_dict(self) -> Dict:
"""
Convert delta to dictionary representation.
Returns:
Dictionary representation of the delta.
"""
def to_flat_dicts(self, include_action_in_path: bool = False, report_type_changes: bool = True) -> List[FlatDeltaRow]:
"""
Convert delta to flat dictionary format.
Parameters:
- include_action_in_path: Whether to include action in path
- report_type_changes: Whether to report type changes
Returns:
List of flat delta row dictionaries.
"""
def to_flat_rows(self, include_action_in_path: bool = False, report_type_changes: bool = True) -> List[FlatDeltaRow]:
"""
Convert delta to flat row format.
Parameters:
- include_action_in_path: Whether to include action in path
- report_type_changes: Whether to report type changes
Returns:
List of flat delta rows.
"""
def reset(self) -> None:
"""
Reset the delta to its initial state.
"""Load delta objects from various serialized formats.
@staticmethod
def _from_flat_rows(flat_rows_list: List[FlatDeltaRow]) -> 'Delta':
"""
Create Delta from flat rows list.
Parameters:
- flat_rows_list: List of flat delta rows
Returns:
Delta object created from flat rows.
"""
@staticmethod
def _from_flat_dicts(flat_dict_list: List[Dict]) -> 'Delta':
"""
Create Delta from flat dictionaries list.
Parameters:
- flat_dict_list: List of flat dictionaries
Returns:
Delta object created from flat dictionaries.
"""Apply delta objects to create modified versions of objects.
def apply_to(self, obj: Any) -> Any:
"""
Apply delta to an object, potentially mutating it.
Parameters:
- obj: Object to apply delta to
Returns:
Modified object (same object if mutate=True, new object if mutate=False).
"""
def create_new_from(self, obj: Any) -> Any:
"""
Create a new object by applying delta to the provided object.
Parameters:
- obj: Base object to apply delta to
Returns:
New object with delta applied (never mutates original).
"""Delta objects support mathematical operators for easy application.
def __add__(self, other: Any) -> Any:
"""
Apply delta using + operator.
Usage: result = delta + original_object
Parameters:
- other: Object to apply delta to
Returns:
Object with delta applied.
"""
def __radd__(self, other: Any) -> Any:
"""
Apply delta using + operator (reverse).
Usage: result = original_object + delta
Parameters:
- other: Object to apply delta to
Returns:
Object with delta applied.
"""from deepdiff import DeepDiff, Delta
# Create objects
original = {"name": "John", "age": 30, "city": "New York"}
modified = {"name": "John", "age": 31, "city": "Boston"}
# Create diff and delta
diff = DeepDiff(original, modified)
delta = Delta(diff)
# Apply delta to recreate modified object
result = delta + original
print(result == modified) # True
# Alternative application method
result2 = delta.apply_to(original.copy())
print(result2 == modified) # True# Serialize delta to JSON
delta_json = delta.dumps()
print(delta_json)
# Save delta to file
delta.dump("changes.json")
# Load delta from file
loaded_delta = Delta.load("changes.json")
# Apply loaded delta
result = loaded_delta + original# Create bidirectional delta for reverse operations
diff = DeepDiff(original, modified)
bidirectional_delta = Delta(diff, bidirectional=True)
# Apply forward
forward_result = bidirectional_delta + original
print(forward_result == modified) # True
# Apply reverse (if supported by the changes)
reverse_result = bidirectional_delta + modified
print(reverse_result == original) # May be True depending on change types# Non-mutating delta (default)
delta = Delta(diff, mutate=False)
original_copy = original.copy()
result = delta.apply_to(original_copy)
print(original_copy == original) # True - original not modified
# Mutating delta
delta_mutating = Delta(diff, mutate=True)
original_copy = original.copy()
result = delta_mutating.apply_to(original_copy)
print(original_copy == modified) # True - original was modified
print(result is original_copy) # True - same object returned# Work with nested structures
nested_original = {
"user": {"name": "John", "profile": {"age": 30, "interests": ["reading"]}},
"settings": {"theme": "light", "notifications": True}
}
nested_modified = {
"user": {"name": "John", "profile": {"age": 31, "interests": ["reading", "coding"]}},
"settings": {"theme": "dark", "notifications": True},
"metadata": {"last_updated": "2023-01-01"}
}
diff = DeepDiff(nested_original, nested_modified)
delta = Delta(diff)
# Apply complex changes
result = delta + nested_original
print(result == nested_modified) # True# Enable error logging
delta = Delta(diff, log_errors=True)
try:
# Apply delta to incompatible object
incompatible = {"completely": "different", "structure": True}
result = delta + incompatible
except Exception as e:
print(f"Delta application failed: {e}")# Control what modules can be imported during deserialization
safe_modules = ["datetime", "collections", "json"]
delta = Delta(diff, safe_to_import=safe_modules)
# Serialize with custom objects
delta_str = delta.dumps()
# Load with safety restrictions
loaded_delta = Delta.loads(delta_str, safe_to_import=safe_modules)# Delta operations on lists
list_original = [1, 2, 3, 4, 5]
list_modified = [1, 2, 4, 5, 6] # Removed 3, added 6
diff = DeepDiff(list_original, list_modified)
delta = Delta(diff)
result = delta + list_original
print(result) # [1, 2, 4, 5, 6]# Create multiple deltas and chain them
step1 = {"value": 10}
step2 = {"value": 20}
step3 = {"value": 30}
# Create deltas for each step
delta1 = Delta(DeepDiff(step1, step2))
delta2 = Delta(DeepDiff(step2, step3))
# Apply deltas sequentially
result = delta2 + (delta1 + step1)
print(result == step3) # True# Delta serialization formats
SerializationFormat = Union['json', 'pickle', 'dill']
# Delta application modes
ApplicationMode = Union['mutate', 'create_new']
# Delta direction for bidirectional operations
DeltaDirection = Union['forward', 'reverse']
# Safe import configuration
SafeImportList = List[str]
# Delta error information
class DeltaError(Exception):
"""Base exception for Delta operations."""
class DeltaUnflattenError(DeltaError):
"""Exception raised when Delta cannot be unflattened."""
# Delta serialization options
class DeltaSerializationOptions:
format: SerializationFormat
pretty_print: bool
compression: bool
safe_to_import: SafeImportListInstall with Tessl CLI
npx tessl i tessl/pypi-deepdiff