The code below reproduces the issue:
from collections import OrderedDict
from ruamel.yaml import YAML
ordered_dict = OrderedDict(a = 1, b = 2)
replacement = dict(a = 3, b = 4)
ordered_dict.update(**replacement)
print(ordered_dict) # this is to show that OrderedDict is compatible with dict
commented_map = YAML().load('''\
a: 1
b: 2
''')
commented_map.update(**replacement) # should work like dict's update()
print(commented_map)
Output
The first part
OrderedDict([('a', 3), ('b', 4)])
shows that OrderedDict
is compatible with dict
However the commented_map
part raises an exception
Traceback (most recent call last):
File "ruamel_bug.py", line 14, in <module>
commented_map.update(**replacement)
File "D:\venv\Ruamel\lib\site-packages\ruamel\yaml\comments.py", line 881, in update
self._ok.add(*kw.keys())
TypeError: set.add() takes exactly one argument (2 given)
My current work-around is to edit the source code to modify line 881 into
for key in kw.keys(): self._ok.add(key)
then everything became OK!!! Therefore I believe it is a bug in line 881.
I was going to create a ticket for the project, but the instruction asked me to post here first, to clarify that it is not a faulty usage of the library.
Is it a bug? Or my misusage?
Thank you in advance.
Environment: ruamel.yaml==0.17.21 with Python 3.11 on 64 bit Windows
Since the intention is that CommentedMap
behaves like a dict
, and this has been implemeted for dict
's so long ago, this should probably be called a bug instead of a missing feature. I added a ticket on sourceforge for this.
In ruamel.ordereddict
, the implementation of the original C mapping that kept insertion order (on which CommentedMap
for Python 2 relies heavily), the .update()
doesn't take keywords either. That package was developed back in 2007, still three years after Python 2.4 was released, so that is IMO somewhat more understandable it is not in there. So maybe that is why this is not (fully) implemented in ruamel.yaml
Until that has been fixed (done in 0.17.23), you can do update(replacement)
(i.e. pass in the dict as parameter) instead of expanding them to key-value parameters with update(**replacement)