| 
16 | 16 | import copy  | 
17 | 17 | from collections import deque  | 
18 | 18 | 
 
  | 
 | 19 | +from bson import RE_TYPE  | 
19 | 20 | from bson.code import Code  | 
20 | 21 | from bson.son import SON  | 
21 | 22 | from pymongo import helpers, message, read_preferences  | 
@@ -184,7 +185,7 @@ def __clone(self, deepcopy=True):  | 
184 | 185 |         data = dict((k, v) for k, v in self.__dict__.iteritems()  | 
185 | 186 |                     if k.startswith('_Cursor__') and k[9:] in values_to_clone)  | 
186 | 187 |         if deepcopy:  | 
187 |  | -            data = copy.deepcopy(data)  | 
 | 188 | +            data = self.__deepcopy(data)  | 
188 | 189 |         clone.__dict__.update(data)  | 
189 | 190 |         return clone  | 
190 | 191 | 
 
  | 
@@ -823,3 +824,24 @@ def __deepcopy__(self, memo):  | 
823 | 824 |         .. versionadded:: 2.3+  | 
824 | 825 |         """  | 
825 | 826 |         return self.__clone(deepcopy=True)  | 
 | 827 | + | 
 | 828 | +    def __deepcopy(self, x, memo=None):  | 
 | 829 | +        """Deepcopy helper for the data dictionary.  | 
 | 830 | +
  | 
 | 831 | +        Regular expressions cannot be deep copied but as they are immutable we  | 
 | 832 | +        don't have to copy them when cloning.  | 
 | 833 | +        """  | 
 | 834 | +        y = {}  | 
 | 835 | +        if memo is None:  | 
 | 836 | +            memo = {}  | 
 | 837 | +        val_id = id(x)  | 
 | 838 | +        if val_id in memo:  | 
 | 839 | +            return memo.get(val_id)  | 
 | 840 | +        memo[val_id] = y  | 
 | 841 | +        for key, value in x.iteritems():  | 
 | 842 | +            if isinstance(value, dict):  | 
 | 843 | +                value = self.__deepcopy(value, memo)  | 
 | 844 | +            elif not isinstance(value, RE_TYPE):  | 
 | 845 | +                value = copy.deepcopy(value, memo)  | 
 | 846 | +            y[copy.deepcopy(key, memo)] = value  | 
 | 847 | +        return y  | 
0 commit comments