1
1
import copy
2
- from typing import Any , Dict , Optional
3
- from pydantic . v1 import BaseModel
2
+ from typing import Any
3
+
4
4
5
5
class DeepCopyError (Exception ):
6
6
"""Custom exception raised when an object cannot be deep-copied."""
7
+
7
8
pass
8
9
10
+
11
+ def is_boto3_client (obj ):
12
+ import sys
13
+
14
+ # check boto3 module imprort
15
+ boto3_module = sys .modules .get ("boto3" )
16
+
17
+ if boto3_module :
18
+ # boto3 use botocore client so here we import botocore
19
+ # if boto3 was imported the botocore will be import automatically normally
20
+ try :
21
+ from botocore .client import BaseClient
22
+
23
+ return isinstance (obj , BaseClient )
24
+ except (AttributeError , ImportError ):
25
+ # if the module is not imported, or the BaseClient class does not exist, return False
26
+ # if custome module name is boto3, the BaseClient class does not exist,
27
+ return False
28
+ return False
29
+
30
+
9
31
def safe_deepcopy (obj : Any ) -> Any :
10
32
"""
11
33
Attempts to create a deep copy of the object using `copy.deepcopy`
12
34
whenever possible. If that fails, it falls back to custom deep copy
13
35
logic. If that also fails, it raises a `DeepCopyError`.
14
-
36
+
15
37
Args:
16
38
obj (Any): The object to be copied, which can be of any type.
17
39
@@ -24,7 +46,7 @@ def safe_deepcopy(obj: Any) -> Any:
24
46
"""
25
47
26
48
try :
27
-
49
+
28
50
# Try to use copy.deepcopy first
29
51
return copy .deepcopy (obj )
30
52
except (TypeError , AttributeError ) as e :
@@ -33,43 +55,40 @@ def safe_deepcopy(obj: Any) -> Any:
33
55
# Handle dictionaries
34
56
if isinstance (obj , dict ):
35
57
new_obj = {}
36
-
58
+
37
59
for k , v in obj .items ():
38
60
new_obj [k ] = safe_deepcopy (v )
39
61
return new_obj
40
62
41
63
# Handle lists
42
64
elif isinstance (obj , list ):
43
65
new_obj = []
44
-
66
+
45
67
for v in obj :
46
68
new_obj .append (safe_deepcopy (v ))
47
69
return new_obj
48
70
49
71
# Handle tuples (immutable, but might contain mutable objects)
50
72
elif isinstance (obj , tuple ):
51
73
new_obj = tuple (safe_deepcopy (v ) for v in obj )
52
-
74
+
53
75
return new_obj
54
76
55
77
# Handle frozensets (immutable, but might contain mutable objects)
56
78
elif isinstance (obj , frozenset ):
57
79
new_obj = frozenset (safe_deepcopy (v ) for v in obj )
58
80
return new_obj
59
81
82
+ elif is_boto3_client (obj ):
83
+ return obj
84
+
60
85
# Handle objects with attributes
61
- elif hasattr ( obj , "__dict__" ) :
86
+ else :
62
87
# If an object cannot be deep copied, then the sub-properties of \
63
88
# the object will not be analyzed and shallow copy will be used directly.
64
89
try :
65
90
return copy .copy (obj )
66
91
except (TypeError , AttributeError ):
67
- raise DeepCopyError (f"Cannot deep copy the object of type { type (obj )} " ) from e
68
-
69
-
70
- # Attempt shallow copy as a fallback
71
- try :
72
- return copy .copy (obj )
73
- except (TypeError , AttributeError ):
74
- raise DeepCopyError (f"Cannot deep copy the object of type { type (obj )} " ) from e
75
-
92
+ raise DeepCopyError (
93
+ f"Cannot deep copy the object of type { type (obj )} "
94
+ ) from e
0 commit comments