Ticket #13394: weak_dict.patch

File weak_dict.patch, 7.4 KB (added by nbruin, 6 years ago)

patch for latest update

  • src/sage/misc/weak_dict.pyx

    diff --git a/src/sage/misc/weak_dict.pyx b/src/sage/misc/weak_dict.pyx
    index 091b9bc..881563e 100644
    a b Fast and safe weak value dictionary 
    44AUTHORS:
    55
    66- Simon King (2013-10)
    7 - Nils Bruin (2013-10)src/sage/misc/weak_dict.pyx1
     7- Nils Bruin (2013-10)
    88
    99Python's :mod:`weakref` module provides
    1010:class:`~weakref.WeakValueDictionary`. This behaves similar to a dictionary,
    no error messages, and the items get correctly removed:: 
    6666    sage: len(D)
    6767    0
    6868
    69 Another proplem arises when iterating over the items of a dictionary: If
     69Another problem arises when iterating over the items of a dictionary: If
    7070garbage collection occurs during iteration, then the content of the dictionary
    7171changes, and the iteration breaks for :class:`weakref.WeakValueDictionary`::
    7272
    cdef class WeakValueDictionary(dict): 
    349349
    350350    TESTS::
    351351
    352     The following reflects the behaviour of the callback ov weak dict values,
     352    The following reflects the behaviour of the callback on weak dict values,
    353353    as discussed on :trac:`13394`.  ::
    354354
    355355        sage: from sage.misc.weak_dict import WeakValueDictionary
    cdef class WeakValueDictionary(dict): 
    593593        TESTS:
    594594
    595595        One may wonder whether it causes problems when garbage collection for
    596         a previously exististing item happens *after* overriding the
    597         item. The example shows that it is not a problem::
     596        a previously existing item happens *after* overriding the item. The
     597        example shows that it is not a problem::
    598598
    599599            sage: class Cycle:
    600600            ....:     def __init__(self):
    cdef class _IterationContext: 
    11101110    though. Doing so is a bug in a program (since iteration order is
    11111111    non-deterministic the results are not well-defined)
    11121112
    1113     This is implemented by putting all items that are deleted during iteration
    1114     are not actually deleted, but only *marked* for deletion. Note, however,
    1115     that they behave like items that actually *are* deleted. E.g., it is not
    1116     possible to delete the same item twice::
    1117 
    1118         sage: class Val: pass
    1119         sage: V = [Val() for n in range(3)]
    1120         sage: D = sage.misc.weak_dict.WeakValueDictionary(enumerate(V))
    1121         sage: for k,v in D.iteritems():
    1122         ....:     print k in D.keys()
    1123         ....:     del D[k]
    1124         ....:     print k in D.keys()
    1125         ....:     try:
    1126         ....:         del D[k]
    1127         ....:     except KeyError:
    1128         ....:         print "due error"
    1129         True
    1130         False
    1131         due error
    1132         True
    1133         False
    1134         due error
    1135         True
    1136         False
    1137         due error
     1113    This is implemented by only marking entries for deletion if their values
     1114    become deallocated while an iterator is active. Once the iterator finishes,
     1115    the keys are deallocated. Note that because the weakrefs will be dead, the
     1116    keys in question do not appear to be in the dictionary anymore::
     1117   
     1118        sage: from sage.misc.weak_dict import WeakValueDictionary
     1119        sage: K = [frozenset([i]) for i in range(11)]
     1120        sage: D = WeakValueDictionary((K[i],K[i+1]) for i in range(10))
     1121        sage: k = K[10]
     1122        sage: del K
     1123        sage: i = D.iterkeys(); d = i.next(); del d
     1124        sage: len(D.keys())
     1125        10
     1126        sage: del k
     1127
     1128    At this point, the entry for `k` appears to have disappeared out of `D`,
     1129    but a reference to `k` is still kept, so the other entries in `D` survive::
    11381130
     1131        sage: len(D.keys())
     1132        9
     1133   
     1134    if we delete the iterator `i` the reference to `k` is dropped, and as a result
     1135    all entries will disappear from `D`::
     1136
     1137        sage: del i
     1138        sage: len(D.keys())
     1139        0
     1140   
    11391141    """
    11401142    cdef WeakValueDictionary Dict
    11411143    def __init__(self, Dict):
    cdef class _IterationContext: 
    11501152
    11511153        EXAMPLES::
    11521154
    1153             sage: import sage.misc.weak_dict
    1154             sage: class Val: pass
    1155             sage: V = [Val() for n in range(3)]
    1156             sage: D = sage.misc.weak_dict.WeakValueDictionary(enumerate(V))
    1157             sage: for k,v in D.iteritems():  # indirect doctest
    1158             ....:     k in D.keys()
    1159             ....:     del D[k]
    1160             ....:     k in D.keys()
    1161             True
    1162             False
    1163             True
    1164             False
    1165             True
    1166             False
     1155            sage: from sage.misc.weak_dict import WeakValueDictionary
     1156            sage: K = [frozenset([i]) for i in range(11)]
     1157            sage: D = WeakValueDictionary((K[i],K[i+1]) for i in range(10))
     1158            sage: k = K[10]
     1159            sage: del K
     1160            sage: i = D.iterkeys(); d = i.next(); del d
     1161            sage: len(D.keys())
     1162            10
     1163            sage: del k
     1164            sage: len(D.keys())
     1165            9
     1166            sage: del i
     1167            sage: len(D.keys())
     1168            0
    11671169
    11681170        """
    11691171        self.Dict = Dict
    cdef class _IterationContext: 
    11751177
    11761178        TESTS::
    11771179
    1178             sage: import sage.misc.weak_dict
    1179             sage: class Val: pass
    1180             sage: V = [Val() for n in range(3)]
    1181             sage: D = sage.misc.weak_dict.WeakValueDictionary(enumerate(V))
    1182             sage: for k,v in D.iteritems():        # indirect doctest
    1183             ....:     k in D.keys()
    1184             ....:     del D[k]
    1185             ....:     k in D.keys()
    1186             True
    1187             False
    1188             True
    1189             False
    1190             True
    1191             False
     1180            sage: from sage.misc.weak_dict import WeakValueDictionary
     1181            sage: K = [frozenset([i]) for i in range(11)]
     1182            sage: D = WeakValueDictionary((K[i],K[i+1]) for i in range(10))
     1183            sage: k = K[10]
     1184            sage: del K
     1185            sage: i = D.iterkeys(); d = i.next(); del d
     1186            sage: len(D.keys())
     1187            10
     1188            sage: del k
     1189            sage: len(D.keys())
     1190            9
     1191            sage: del i
     1192            sage: len(D.keys())
     1193            0
    11921194
    11931195        """
    11941196        self.Dict._guard_level += 1
    cdef class _IterationContext: 
    12021204
    12031205        TESTS::
    12041206
    1205             sage: import sage.misc.weak_dict
    1206             sage: class Val: pass
    1207             sage: V = [Val() for n in range(3)]
    1208             sage: D = sage.misc.weak_dict.WeakValueDictionary(enumerate(V))
    1209             sage: for k,v in D.iteritems():      # indirect doctest
    1210             ....:     k in D.keys()
    1211             ....:     del D[k]
    1212             ....:     k in D.keys()
    1213             True
    1214             False
    1215             True
    1216             False
    1217             True
    1218             False
     1207            sage: from sage.misc.weak_dict import WeakValueDictionary
     1208            sage: K = [frozenset([i]) for i in range(11)]
     1209            sage: D = WeakValueDictionary((K[i],K[i+1]) for i in range(10))
     1210            sage: k = K[10]
     1211            sage: del K
     1212            sage: i = D.iterkeys(); d = i.next(); del d
     1213            sage: len(D.keys())
     1214            10
     1215            sage: del k
     1216            sage: len(D.keys())
     1217            9
     1218            sage: del i
     1219            sage: len(D.keys())
     1220            0
    12191221
    1220         """
    1221         # Propagate errors by returning "False"
     1222       """
     1223       # Propagate errors by returning "False"
    12221224        self.Dict._guard_level -= 1
    12231225        #when the guard_level drops to zero, we try to remove all the
    12241226        #pending removals. Note that this could trigger another iterator