В ruamel.yaml, как мне создать ScalarEvent с литеральной строкой "null"? - PullRequest
1 голос
/ 15 января 2020

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

Я не смог создать ScalarEvent со значением "null", например что он появляется в файле YAML как строка 'null', а не как ключевое слово YAML null.

В кодовой форме, если я попытаюсь

dumper = yaml.Dumper(out_file,  width=200)
param = 'field'
param_value = 'null'
dumper.emit(yaml.MappingStartEvent(anchor=None, tag=None, implicit=True, flow_style=True))
dumper.emit(yaml.ScalarEvent(anchor=None, tag=None, implicit=(True, True), value=param))
dumper.emit(yaml.ScalarEvent(anchor=None, tag=None, implicit=(True, True), value=param_value))
dumper.emit(yaml.MappingEndEvent())

, я получу

field: null

, тогда как я хотел бы видеть

field: 'null'

1 Ответ

0 голосов
/ 16 января 2020

Ваш код неполон, но так как вы установили flow_style=True для события отображения, вы не получили код, который вы показали, и никогда не получите желаемый результат.

Если вы хотите на go этот маршрут, затем посмотрите на единственное место в коде, где код ruamel.yaml испускает ScalarNode. Он находится в serializer.py:

            self.emitter.emit(
                ScalarEvent(
                    alias,
                    node.tag,
                    implicit,
                    node.value,
                    style=node.style,
                    comment=node.comment,
                )
            )

. После этого вы выбираете, что вам нужно добавить параметр style. Дальнейшее копание покажет, что это должна быть строка из одного символа, в вашем случае одинарная кавычка ("'"), для форсировки скаляра с одинарными кавычками.

import sys
import ruamel.yaml as yaml

dumper = yaml.Dumper(sys.stdout,  width=200)
param = 'field'
param_value = 'null'
dumper.emit(yaml.StreamStartEvent())
dumper.emit(yaml.DocumentStartEvent())
# !!!! changed flow_style in the next line
dumper.emit(yaml.MappingStartEvent(anchor=None, tag=None, implicit=True, flow_style=False))
dumper.emit(yaml.ScalarEvent(anchor=None, tag=None, implicit=(True, True), value=param))
# added style= in next line
dumper.emit(yaml.ScalarEvent(anchor=None, tag=None, implicit=(True, True), style="'", value=param_value))
dumper.emit(yaml.MappingEndEvent())
dumper.emit(yaml.DocumentEndEvent())
dumper.emit(yaml.StreamEndEvent())

, который дает то, что вы хотите:

field: 'null'

Однако я думаю, что вы делаете свою жизнь более сложной, чем необходимо. ruamel.yaml сохраняет стиль потока при передаче туда и обратно, и вы создаете функциональную структуру данных и создаете дамп, который вместо возврата к управлению дампером с событиями:

import sys
import ruamel.yaml

yaml_str = """\
a:
   - field: 'null'
     x: y
   - {field: 'null', x: y}
"""

yaml = ruamel.yaml.YAML()
data = yaml.load(yaml_str)
for i in range(2):
    data["a"].append(ruamel.yaml.comments.CommentedMap([("a", "b"), ("c", "d")]))
data["a"][-1].fa.set_flow_style()
yaml.dump(data, sys.stdout)

дает:

a:
- field: 'null'
  x: y
- {field: 'null', x: y}
- a: b
  c: d
- {a: b, c: d}
...