Как удалить все комментарии в ruamel.yaml? - PullRequest
0 голосов
/ 05 февраля 2020

По умолчанию ruamel.yaml сохраняет все комментарии. Как я могу отключить эту опцию? Я хочу удалить все комментарии из файла yaml, и эти комментарии могут быть где угодно.

В настоящее время я проверяю каждый элемент и устанавливаю yamldata.ca._items = {}, но это не всегда работает. Иногда он просто удаляет комментарии перед строкой, но не после. Кроме того, он работает только для первого уровня, и для удаления комментариев в подкартах я должен использовать рекурсивную функцию.

Есть ли простой способ удалить все комментарии?

Библиотека pyyaml ​​не сохраняет комментарии, но также не позволяет настраивать отступы и не сохраняет порядок. Удаление всех строк с # из файла также приведет к удалению таких строк, как key: value # comment.

1 Ответ

0 голосов
/ 06 февраля 2020

Если вы заботитесь о порядке ключей и по-прежнему не используете Python 2 (вы не должны), то вы можете просто использовать загрузчик сейфа для загрузки, а затем выполнить дамп с помощью (по умолчанию) обходного дампа:

import sys
import ruamel.yaml

yaml_str = """\
x: # first mapping
   b: 1
   a: 2
y:
   - 3
   - "4" # last_item
"""

yaml = ruamel.yaml.YAML()
yaml.indent(mapping=4, sequence=4, offset=2)
yaml.preserve_quotes = True
yaml.default_flow_style = False

data = ruamel.yaml.YAML(typ='safe').load(yaml_str)
yaml.dump(data, sys.stdout)

, что дает:

x:
    b: 1
    a: 2
y:
  - 3
  - '4'

и, как вы можете видеть, цитаты вокруг 4 изменились.

Если это недопустимо, вы должны загрузить, используя загрузчик туда и обратно, как вы делаете, но вместо этого только удаляя атрибуты комментария items, вы должны просто удалить атрибут, содержащий комментарии полностью.

Это, конечно, нельзя сделать с помощью ca свойство, вам придется удалить сам атрибут. Если комментариев нет, вы фактически создаете пустую структуру комментариев для всех сложных узлов, у которых ее нет, когда используете .ca.

def recursive_delete_comment_attribs(d):
    if isinstance(d, dict):
        for k, v in d.items():
            recursive_delete_comment_attribs(k)
            recursive_delete_comment_attribs(v)
    elif isinstance(d, list):
        for elem in d:
            recursive_delete_comment_attribs(elem)
    try:
         # literal scalarstring might have comment associated with them
         attr = 'comment' if isinstance(d, ruamel.yaml.scalarstring.ScalarString) \
                  else ruamel.yaml.comments.Comment.attrib 
         delattr(d, attr)
    except AttributeError:
        pass



data = yaml.load(yaml_str)
recursive_delete_comment_attribs(data)
yaml.dump(data, sys.stdout)

, что дает:

x:
    b: 1
    a: 2
y:
  - 3
  - "4"
...