Эта проблема в основном возникает из-за ruamel.yaml
разработки
не начинайте со спецификации, к которой относится структура данных вашего комментария #
comment
(и не имеет его сейчас). Дело в том, что это проще
добавить комментарий к уже созданному узлу (т.е. что-то в
Документ YAML до того, как парсер встретит комментарий), чем добавить его
на следующий узел (который в конце документа может не отображаться
вверх).
В вашем примере комментарий может быть связан с ключом f
, чтобы
первый элемент последовательности одного элемента или первый элемент
из двойной последовательности элементов. ruamel.yaml
пытается сделать некоторую перестановку, и это имеет
в результате в прошлом в одном комментарии, связанные с
два последовательных узла, и это то, что merge_comments
пытается решить, посмотрев
равны ли эти комментарии.
Это пробел, но это работает достаточно хорошо
если вы используете ruamel.yaml
по назначению «загрузить-изменить-сохранить», но для глубокого копирования
не сохраняет эту ссылку, что приводит к неравенству и, следовательно, AssertionError
Быстрое и грязное решение для этого состоит в том, чтобы сделать merge_comments
запретом:
import copy
from ruamel.yaml import YAML
yaml = YAML()
conf = None
with open("input.yaml", 'r') as inf:
conf = yaml.load(inf)
conf2 = copy.deepcopy(conf)
with open("out1.yaml", 'w') as outf:
yaml.dump(conf, outf)
yaml.representer.merge_comments = lambda x, y: None
try:
with open("out2.yaml", 'w') as outf:
yaml.dump(conf2, outf)
print("all good")
except AssertionError:
raise SystemExit("Deep copy failed")
, что дает:
all good
С содержанием out1.yaml
:
C:
f:
# comment
- - l1
- l2: '5'
и out2.yaml
:
C:
f:
# comment
- - l1
- l2: '5'
Эта проблема «улучшена» как __deepcopy__
для
представление списка и отображение, делает глубокую копию
атрибуты, которые содержат комментарий, поток, формат, привязку и т. д. информацию
без следования совету в документации :
Если для реализации deepcopy () необходимо сделать глубокую копию
компонент, он должен вызывать функцию deepcopy () с компонентом
в качестве первого аргумента и словарь памятки в качестве второго аргумента.
Но изменение, которое не решает проблему, более структурное решение
было бы иметь недвусмысленное определение того, что комментарий будет применяться и
покончить с merge_comments
. Это должно
включает разделение многострочных комментариев, как в:
# this documents has some non-trivial
# comment lines
# first item follows
- 42
# end of first item
# second item follows
- 196
# end of second item
# final comment of the document
В настоящее время вышеприведенное будет загружаться с тремя (многострочными) комментариями, но IMO
было бы более уместно интерпретировать это как шесть комментариев.
Основной задачей является определение разбиения таких комментариев без интерпретации значения комментария, а только с использованием пустых строк.
Кроме того, для назначения узла может учитываться уровень отступа комментария.