Skip to content

Commit 3327312

Browse files
authored
Merge pull request #671 from goasleep/fix/fix_boto3_client_copy
fix:fix boto3 client copy
2 parents c3b93d6 + 7e3f66e commit 3327312

File tree

2 files changed

+42
-17
lines changed

2 files changed

+42
-17
lines changed

scrapegraphai/utils/copy.py

Lines changed: 36 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,39 @@
11
import copy
2-
from typing import Any, Dict, Optional
3-
from pydantic.v1 import BaseModel
2+
from typing import Any
3+
44

55
class DeepCopyError(Exception):
66
"""Custom exception raised when an object cannot be deep-copied."""
7+
78
pass
89

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+
931
def safe_deepcopy(obj: Any) -> Any:
1032
"""
1133
Attempts to create a deep copy of the object using `copy.deepcopy`
1234
whenever possible. If that fails, it falls back to custom deep copy
1335
logic. If that also fails, it raises a `DeepCopyError`.
14-
36+
1537
Args:
1638
obj (Any): The object to be copied, which can be of any type.
1739
@@ -24,7 +46,7 @@ def safe_deepcopy(obj: Any) -> Any:
2446
"""
2547

2648
try:
27-
49+
2850
# Try to use copy.deepcopy first
2951
return copy.deepcopy(obj)
3052
except (TypeError, AttributeError) as e:
@@ -33,43 +55,40 @@ def safe_deepcopy(obj: Any) -> Any:
3355
# Handle dictionaries
3456
if isinstance(obj, dict):
3557
new_obj = {}
36-
58+
3759
for k, v in obj.items():
3860
new_obj[k] = safe_deepcopy(v)
3961
return new_obj
4062

4163
# Handle lists
4264
elif isinstance(obj, list):
4365
new_obj = []
44-
66+
4567
for v in obj:
4668
new_obj.append(safe_deepcopy(v))
4769
return new_obj
4870

4971
# Handle tuples (immutable, but might contain mutable objects)
5072
elif isinstance(obj, tuple):
5173
new_obj = tuple(safe_deepcopy(v) for v in obj)
52-
74+
5375
return new_obj
5476

5577
# Handle frozensets (immutable, but might contain mutable objects)
5678
elif isinstance(obj, frozenset):
5779
new_obj = frozenset(safe_deepcopy(v) for v in obj)
5880
return new_obj
5981

82+
elif is_boto3_client(obj):
83+
return obj
84+
6085
# Handle objects with attributes
61-
elif hasattr(obj, "__dict__"):
86+
else:
6287
# If an object cannot be deep copied, then the sub-properties of \
6388
# the object will not be analyzed and shallow copy will be used directly.
6489
try:
6590
return copy.copy(obj)
6691
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

tests/utils/copy_utils_test.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -184,3 +184,9 @@ def test_with_pydantic():
184184
copy_obj = safe_deepcopy(original)
185185
assert copy_obj.value == original.value
186186
assert copy_obj is not original
187+
188+
def test_with_boto3():
189+
import boto3
190+
boto_client = boto3.client("bedrock-runtime", region_name="us-west-2")
191+
copy_obj = safe_deepcopy(boto_client)
192+
assert copy_obj == boto_client

0 commit comments

Comments
 (0)