Skip to content

Commit

Permalink
Catch Exceptions in smart_deepcopy (#4187)
Browse files Browse the repository at this point in the history
* Catch Exceptions in smart_deepcopy

* address feedback
  • Loading branch information
coneybeare committed Aug 12, 2022
1 parent fa6b978 commit b8a6957
Show file tree
Hide file tree
Showing 3 changed files with 20 additions and 3 deletions.
1 change: 1 addition & 0 deletions changes/4184-coneybeare.md
@@ -0,0 +1 @@
Catch certain raised errors in `smart_deepcopy` and revert to `deepcopy` if so.
11 changes: 8 additions & 3 deletions pydantic/utils.py
Expand Up @@ -684,9 +684,14 @@ def smart_deepcopy(obj: Obj) -> Obj:
obj_type = obj.__class__
if obj_type in IMMUTABLE_NON_COLLECTIONS_TYPES:
return obj # fastest case: obj is immutable and not collection therefore will not be copied anyway
elif not obj and obj_type in BUILTIN_COLLECTIONS:
# faster way for empty collections, no need to copy its members
return obj if obj_type is tuple else obj.copy() # type: ignore # tuple doesn't have copy method
try:
if not obj and obj_type in BUILTIN_COLLECTIONS:
# faster way for empty collections, no need to copy its members
return obj if obj_type is tuple else obj.copy() # type: ignore # tuple doesn't have copy method
except (TypeError, ValueError, RuntimeError):
# do we really dare to catch ALL errors? Seems a bit risky
pass

return deepcopy(obj) # slowest way when we actually might need a deepcopy


Expand Down
11 changes: 11 additions & 0 deletions tests/test_utils.py
Expand Up @@ -461,6 +461,17 @@ def test_smart_deepcopy_collection(collection, mocker):
assert smart_deepcopy(collection) is expected_value


@pytest.mark.parametrize('error', [TypeError, ValueError, RuntimeError])
def test_smart_deepcopy_error(error, mocker):
class RaiseOnBooleanOperation(str):
def __bool__(self):
raise error('raised error')

obj = RaiseOnBooleanOperation()
expected_value = deepcopy(obj)
assert smart_deepcopy(obj) == expected_value


T = TypeVar('T')


Expand Down

0 comments on commit b8a6957

Please sign in to comment.