Protect a list during modification by modifying a copy instead of the original.
ListProtect creates a copy of a list before running operations like .append(), and prevents
errors on the original object by destroying the copy if an error is encountered, only
overwriting the original if no errors occur.
Parameters:
| Name |
Type |
Description |
Default |
original |
list
|
The original Python list. A copy will be made during any operations, and will only overwrite
|
required
|
Usage:
| ex_list = [1, 2, 3]
## Protects from a ZeroDivision error
with ListProtect(ex_list) as copy:
copy.append(1/0)
print(f'List: {ex_list}')
|
Source code in src/red_utils/std/context_managers/object_managers/protect.py
| class ListProtect:
"""Protect a list during modification by modifying a copy instead of the original.
ListProtect creates a copy of a list before running operations like .append(), and prevents
errors on the original object by destroying the copy if an error is encountered, only
overwriting the original if no errors occur.
Params:
original (list): The original Python `list`. A copy will be made during any operations, and will only overwrite
the original if the operation succeeds.
Usage:
``` py linenums="1"
ex_list = [1, 2, 3]
## Protects from a ZeroDivision error
with ListProtect(ex_list) as copy:
copy.append(1/0)
print(f'List: {ex_list}')
```
"""
def __init__(self, original: list):
## Call immediately after with ListProtect() as copy.
if not isinstance(original, list):
raise TypeError(
f"Invalid type for protected list: ({type(original)}). Must be of type list."
)
## Set class value to original list
self.original = original
def __enter__(self):
## Call after initializing ListProtect instance.
## Create a copy of the list to work on
self.clone: list = self.original.copy()
return self.clone
def __exit__(self, exc_type, exc_value, exc_traceback):
## Call if ListProtect context manager encounters an error.
## No exception encountered, update original
# list and return
if exc_type is None:
self.original[:] = self.clone
## Error encountered, print details
else:
## https://docs.python.org/3/library/inspect.html?highlight=currentframe
frame = inspect.currentframe()
## Full path to error file
file_name = frame.f_code.co_filename
## Line number where error occurred.
file_no = frame.f_lineno
## Build error details dict
err = {
"success": False,
"detail": {
"module": file_name,
"line": file_no,
"exception_type": exc_type,
"exception_text": exc_value,
},
}
## Return error, exit returning original list
print(
f"[ERROR] Error encountered running list operation on protected list. Details: \n{err}"
)
return True
|