Repository navigation
Non-working code in update() method of weakref.WeakKeyDictionary #124748
Copy link
Copy link
Closed
Labels
interpreter-core(Objects, Python, Grammar, and Parser dirs)(Objects, Python, Grammar, and Parser dirs)type-bugAn unexpected behavior, bug, or errorAn unexpected behavior, bug, or error
Description
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)] = valueb) 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)] = valueThanks
CPython versions tested on:
3.13
Operating systems tested on:
Linux
Linked PRs
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
interpreter-core(Objects, Python, Grammar, and Parser dirs)(Objects, Python, Grammar, and Parser dirs)type-bugAn unexpected behavior, bug, or errorAn unexpected behavior, bug, or error
Activity
picnixz commentedon Sep 29, 2024
I don't know whether this is a bug or not, namely I'm not sure that adding
__weakref__to a subclass ofstrshould effectively turn that class into a weak-referencable class.cfbolz commentedon Sep 29, 2024
@ri-gilfanov could you explain what you want your code to do? Is your main point that it's strange that update accepts keyword arguments, but using that feature will always raise?
(imo the use of a
strsubclass is a distraction here. You would get an identical error for any other object that you pass via keyword arguments to update).rigilfanov commentedon Sep 30, 2024
@cfbolz, yes, almost. The update method also contains the code to handling keyword arguments:
My main point is the following. User can call the method with keyword arguments. User can find the source code for handling keyword arguments. But using that feature will always raises a type error. It's looks like a bug.
You are right. I will update the example a bit later.
I implemented the flyweight pattern for a hashable user objects. I needed a dictionary that would store keys and values as weak references. And I used the source code of
WeakKeyDictionaryandWeakValueDictionaryas a starting point.The solution works. However, I decided to cover my code with unit tests. So, I discovered that I inherited non-working code from the
WeakKeyDictionary. So, I decided to write a little bug report.@picnixz, adding the
__slots__is a recommended optimization forstrsubclasses. No more. We can just use subclasses of thedict,listandstrtypes with weak references. Working example:cfbolz commentedon Sep 30, 2024
Here's an example without any kind of subclass to talk about your problem:
I think it would be reasonable to remove the last two lines of
updateand raise an explicit error instead. Like your Option 1, but the exception should be aTypeErrorfor backwards compatibility reasons.rigilfanov commentedon Sep 30, 2024
@cfbolz , thanks. I updated first comment in this issue. Also I updated the error message in option 1.
pythongh-124748: Fix handling **kwargs in WeakKeyDictionary.update()
pythongh-124748: Fix handling kwargs in WeakKeyDictionary.update()
pythongh-124748: Fix handling kwargs in WeakKeyDictionary.update()
pythongh-124748: Fix handling kwargs in WeakKeyDictionary.update()
pythongh-124748: Fix handling kwargs in WeakKeyDictionary.update()
pythongh-124748: Fix handling kwargs in WeakKeyDictionary.update()
pythongh-124748: Fix handling kwargs in WeakKeyDictionary.update()
pythongh-124748: Fix handling kwargs in WeakKeyDictionary.update()
pythongh-124748: Fix handling kwargs in WeakKeyDictionary.update()
pythongh-124748: Fix handling kwargs in WeakKeyDictionary.update()
pythongh-124748: Fix handling kwargs in WeakKeyDictionary.update()
pythongh-124748: Fix handling kwargs in WeakKeyDictionary.update()
robkarlson104 commentedon Feb 16, 2026
Merge branch 'main' into pythongh-124748
gh-124748: Fix handling kwargs in `WeakKeyDictionary.update()` (#124783)
sergey-miryanov commentedon Feb 18, 2026
Completed via #124783
rigilfanov commentedon Feb 20, 2026
@sergey-miryanov , thank you very much!
pythongh-124748: Fix handling kwargs in `WeakKeyDictionary.update()` (p…
pythongh-124748: Fix handling kwargs in `WeakKeyDictionary.update()` (p…