Bug report
Bug description:
Edited at 2024.09.30 10:07 AM.
Example of code
import weakref d = weakref.WeakKeyDictionary() d.update(x=1)
Traceback
Traceback (most recent call last):
File "/home/username/example.py", line 4, in <module>
d.update(x=1)
~~~~~~~~^^^^^
File "/home/username/.pyenv/versions/3.13.0rc2/lib/python3.13/weakref.py", line 518, in update
self.update(kwargs)
~~~~~~~~~~~^^^^^^^^
File "/home/username/.pyenv/versions/3.13.0rc2/lib/python3.13/weakref.py", line 516, in update
d[ref(key, self._remove)] = value
~~~^^^^^^^^^^^^^^^^^^^
TypeError: cannot create weak reference to 'str' object
Source of error
class WeakKeyDictionary(_collections_abc.MutableMapping): ... def update(self, dict=None, /, **kwargs): # `kwargs` always use 'str' for keys d = self.data if dict is not None: if not hasattr(dict, "items"): dict = type({})(dict) for key, value in dict.items(): d[ref(key, self._remove)] = value if len(kwargs): # If true, then `kwargs` contains a key of `str` type self.update(kwargs) # So this line always raises `TypeError`
Proposals
Option 1
a) Add a clear exception and delete last two lines:
class WeakKeyDictionary(_collections_abc.MutableMapping): ... def update(self, dict=None, /, **kwargs): if kwargs: raise TypeError( "Keyword arguments are not supported. " "Can not create weak references to `str` keys." ) d = self.data if dict is not None: if not hasattr(dict, "items"): dict = type({})(dict) for key, value in dict.items(): d[ref(key, self._remove)] = value
b) Write about this behavior in the documentation.
Option 2
a) Remove the kwargs parameter from WeakKeyDicionary.update().
b) Inherit WeakKeyDicionary from Mapping to avoid violating of the Liskov Substitution Principle with MutableMapping.
class WeakKeyDictionary(_collections_abc.Mapping): ... def update(self, dict=None): d = self.data if dict is not None: if not hasattr(dict, "items"): dict = type({})(dict) for key, value in dict.items(): d[ref(key, self._remove)] = value
Thanks
CPython versions tested on:
3.13
Operating systems tested on:
Linux