40
40
List ,
41
41
Optional ,
42
42
Sequence ,
43
+ Set ,
43
44
Tuple ,
44
45
Union ,
45
46
cast ,
@@ -187,14 +188,15 @@ def clone(
187
188
except Exception :
188
189
pass
189
190
191
+ visited : Set [Tuple [int , int ]] = set ()
190
192
d__ = cast (
191
193
"DictionaryObject" ,
192
194
self ._reference_clone (self .__class__ (), pdf_dest , force_duplicate ),
193
195
)
194
196
if ignore_fields is None :
195
197
ignore_fields = []
196
198
if len (d__ .keys ()) == 0 :
197
- d__ ._clone (self , pdf_dest , force_duplicate , ignore_fields )
199
+ d__ ._clone (self , pdf_dest , force_duplicate , ignore_fields , visited )
198
200
return d__
199
201
200
202
def _clone (
@@ -203,6 +205,7 @@ def _clone(
203
205
pdf_dest : PdfWriterProtocol ,
204
206
force_duplicate : bool ,
205
207
ignore_fields : Optional [Sequence [Union [str , int ]]],
208
+ visited : Set [Tuple [int , int ]],
206
209
) -> None :
207
210
"""
208
211
Update the object from src.
@@ -270,6 +273,14 @@ def _clone(
270
273
cur_obj .__class__ (), pdf_dest , force_duplicate
271
274
),
272
275
)
276
+ # check to see if we've previously processed our item
277
+ if clon .indirect_reference is not None :
278
+ idnum = clon .indirect_reference .idnum
279
+ generation = clon .indirect_reference .generation
280
+ if (idnum , generation ) in visited :
281
+ cur_obj = None
282
+ break
283
+ visited .add ((idnum , generation ))
273
284
objs .append ((cur_obj , clon ))
274
285
assert prev_obj is not None
275
286
prev_obj [NameObject (k )] = clon .indirect_reference
@@ -282,7 +293,7 @@ def _clone(
282
293
except Exception :
283
294
cur_obj = None
284
295
for s , c in objs :
285
- c ._clone (s , pdf_dest , force_duplicate , ignore_fields )
296
+ c ._clone (s , pdf_dest , force_duplicate , ignore_fields , visited )
286
297
287
298
for k , v in src .items ():
288
299
if k not in ignore_fields :
@@ -798,6 +809,7 @@ def _clone(
798
809
pdf_dest : PdfWriterProtocol ,
799
810
force_duplicate : bool ,
800
811
ignore_fields : Optional [Sequence [Union [str , int ]]],
812
+ visited : Set [Tuple [int , int ]],
801
813
) -> None :
802
814
"""
803
815
Update the object from src.
@@ -820,7 +832,7 @@ def _clone(
820
832
)
821
833
except Exception :
822
834
pass
823
- super ()._clone (src , pdf_dest , force_duplicate , ignore_fields )
835
+ super ()._clone (src , pdf_dest , force_duplicate , ignore_fields , visited )
824
836
825
837
def get_data (self ) -> Union [bytes , str ]:
826
838
return self ._data
@@ -1048,6 +1060,7 @@ def clone(
1048
1060
except Exception :
1049
1061
pass
1050
1062
1063
+ visited : Set [Tuple [int , int ]] = set ()
1051
1064
d__ = cast (
1052
1065
"ContentStream" ,
1053
1066
self ._reference_clone (
@@ -1056,7 +1069,7 @@ def clone(
1056
1069
)
1057
1070
if ignore_fields is None :
1058
1071
ignore_fields = []
1059
- d__ ._clone (self , pdf_dest , force_duplicate , ignore_fields )
1072
+ d__ ._clone (self , pdf_dest , force_duplicate , ignore_fields , visited )
1060
1073
return d__
1061
1074
1062
1075
def _clone (
@@ -1065,6 +1078,7 @@ def _clone(
1065
1078
pdf_dest : PdfWriterProtocol ,
1066
1079
force_duplicate : bool ,
1067
1080
ignore_fields : Optional [Sequence [Union [str , int ]]],
1081
+ visited : Set [Tuple [int , int ]],
1068
1082
) -> None :
1069
1083
"""
1070
1084
Update the object from src.
@@ -1081,7 +1095,7 @@ def _clone(
1081
1095
self ._operations = list (src_cs ._operations )
1082
1096
self .forced_encoding = src_cs .forced_encoding
1083
1097
# no need to call DictionaryObjection or anything
1084
- # like super(DictionaryObject,self)._clone(src, pdf_dest, force_duplicate, ignore_fields)
1098
+ # like super(DictionaryObject,self)._clone(src, pdf_dest, force_duplicate, ignore_fields, visited )
1085
1099
1086
1100
def _parse_content_stream (self , stream : StreamType ) -> None :
1087
1101
# 7.8.2 Content Streams
0 commit comments