New submission from Daniel Romberg <dan...@romberg.io>:

The copy operation is not safe to use during iteration. The following test case 
raises a "RuntimeError: dictionary changed size during iteration":


import weakref

class Class:
  pass

def TEST_weakValue():
  d = weakref.WeakValueDictionary()
  a = Class()
  b = Class()
  d["a"] = a
  d["b"] = b
  e = d.copy()
  
  for key in e:
    a = None
    c = e.copy()

TEST_weakValue()


This is related to https://bugs.python.org/issue35615 where I commented as 
well, but I couldn't find a way to reopen this issue, which is why I open this 
one.

We experience a lot fewer crashes in weakref than before 
https://bugs.python.org/issue35615 had been fixed, however, there are recursive 
situations in which copy() is invoked while iterating the WeakValueDictionary 
(e.g., in our case it is a signal/slot implementation where the slots are 
stored in a WeakValueDictionary). _commit_removals(), which is called at the 
beginning of the copy operation, might change the dictionary if there are items 
that are to be removed. If there is an ongoing iteration, the corresponding 
RuntimeError is raised.

I haven't thought that through entirely, but I wonder whether the copy (and 
also deepcopy) operation could just blindly copy everything without "committing 
removals". After the copy, both instances would do their _commit_removals on 
their own upon access.

----------
components: Library (Lib)
messages: 385779
nosy: djromberg
priority: normal
severity: normal
status: open
title: copying WeakValueDictionary is not iteration safe
type: crash
versions: Python 3.10, Python 3.6, Python 3.7, Python 3.8, Python 3.9

_______________________________________
Python tracker <rep...@bugs.python.org>
<https://bugs.python.org/issue43041>
_______________________________________
_______________________________________________
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com

Reply via email to