The thing missing form the error message displayed is the line number (I assume that it is 9). That points to the line
if elem['name'] == 'Stuart':
And if that doesn't give you a clue, the approach that I recommend in such cases is starting to add some print functions, so that you know what you are working on. The for loop looks like:
for elem in data:
print('elem', elem)
if elem['name'] == 'Stuart':
print('elem->hobbies', elem['hobbies'])
elem['hobbies'] = ['Fishing']
this prints
elem team_member
before the exception is thrown, and I hope that will make you realize your are not iterating over the elements (items) of a list, but over the keys of a dict (constructed from the root level mapping in your YAML). And the value associated with the key is the object having a key name and a key hobbies.
So change the variable elem to key to make clear what you're handling and then proceed to work with value, the value associated with that key instead of elem within that loop¹:
for key in data:
value = data[key]
if value['name'] == 'Stuart':
print('value->hobbies', value['hobbies'])
value['hobbies'] = ['Fishing']
This gives:
value->hobbies ['dancing']
team_member:
name: Max
hobbies:
- Reading
team_leader:
name: Stuart
hobbies:
- Fishing
So we got rid of the exception, but the result is not exactly what you want. The element dancing for the key 'hobbies' is gone, because you assign a new (list) value to that key, whereas what you should do is append a single item to the list. We can also get rid of the print function by now:
for key in data:
value = data[key]
if value['name'] == 'Stuart':
value['hobbies'].append('Fishing')
This will get you two items in the final sequence in the file. There is a few more things to address:
- the capitalization of
dancing incorrect. To correct that, add a line handling the list if there is only one element
- the code for the name
Max, needs to be added (and that is why you need to get rid of the break in your code)
- the empty line, is considered a comment on the last element of the first sequence, that comment needs to be moved
- your indentation of sequences is non-default
The final code would be like:
from pathlib import Path
import ruamel.yaml
path = Path('input.yaml')
yaml = ruamel.yaml.YAML()
yaml.indent(sequence=4, offset=2) # for the non-default indentation of sequences
data = yaml.load(path)
for key in data:
value = data[key]
if value['name'] == 'Stuart':
if len(value['hobbies']) == 1:
value['hobbies'][0] = value['hobbies'][0].capitalize()
value['hobbies'].append('Fishing')
elif value['name'] == 'Max':
last_item_index = len(value['hobbies']) - 1
value['hobbies'].append('Painting')
comments = value['hobbies'].ca
if not comments.items[last_item_index][0].value.strip():
# move empty comment lines from previous last item to new last item
comments.items[last_item_index + 1] = comments.items.pop(last_item_index)
yaml.dump(data, path)
Which gives something quite close to what you wanted to get
team_member:
name: Max
hobbies:
- Reading
- Painting
team_leader:
name: Stuart
hobbies:
- Dancing
- Fishing
¹Alternative for the first two lines: for key, value in data.items()