簡體   English   中英

如何在使用 ruamel.yaml 加載和轉儲時使用 yamllint 強制注釋位置有效?

[英]How to force the comment position to be valid with yamllint when load and dump with ruamel.yaml?

我希望能夠在 yaml 文檔中“重新定位”現有注釋,以便在對生成的輸出運行yamllint時它們是有效的,默認配置為min-spaces-from-content=2 (參考: https://yamllint .readthedocs.io/en/stable/rules.html#module-yamllint.rules.comments )。

根據How can I add a comment with ruamel.yaml ,使用類似yaml_add_eol_comment('the comment', 'the key', column=None)應該可以解決問題,但這不是我到目前為止得到的結果。

這里是(使用一段代碼ruamel.yaml版本0.16.7 )我寫證明我在當前的行為:

"""Play with comments."""
from __future__ import print_function
import sys
import ruamel.yaml

yaml = ruamel.yaml.YAML()
yaml.indent(mapping=2, sequence=4, offset=2)
inp = """\
---
list-of-maps:
  - part_no:   A4786 # comment 1
    part_henon: mouhaha    # you're not funny
  - part_yes: A21 # also a comment here
    part_iculier: partenaire # I don't always understand how it works
    part_third: key # komment
list-only:
  - first # comment 2
  - third # I have a comment too
  - second # what?
simple-map:
  what-are-you-waiting-for: christmas? # duke nukem rulez
  jingle: bels # not christmas yet
map-of-maps:
  key:
    another-sub-key: w00t # casimir
    sub-key: sub-value # comment 3
    my-sub-key-name-is-longuer-than-yours: 1 # sentinel vs superman
"""

data = yaml.load(inp)


def process_comments(data, column=None):
    if isinstance(data, dict):
        if data.ca:
            if data.ca.items:
                for key in data.ca.items.keys():
                    if data.ca.items[key][2]:
                        comment = data.ca.items[key][2].value.replace("\n", "")
                        data.yaml_add_eol_comment(comment, key, column=column)
        for k, v in data.items():
            process_comments(k, column=column)
            process_comments(v, column=column)
    elif isinstance(data, list):
        if data.ca:
            if data.ca.items:
                for key in data.ca.items.keys():
                    if data.ca.items[key][0]:
                        comment = data.ca.items[key][0].value.replace("\n", "")
                        data.yaml_add_eol_comment(comment, key, column=column)
        for elem in data:
            process_comments(elem, column=column)


process_comments(data, column=None)
yaml.dump(data, sys.stdout)

預期的輸出是:

list-of-maps:
  - part_no: A4786  # comment 1
    part_henon: mouhaha  # you're not funny
  - part_yes: A21  # also a comment here
    part_iculier: partenaire  # I don't always understand how it works
    part_third: key  # komment
list-only:
  - first  # comment 2
  - third  # I have a comment too
  - second  # what?
simple-map:
  what-are-you-waiting-for: christmas?  # duke nukem rulez
  jingle: bels  # not christmas yet
map-of-maps:
  key:
    another-sub-key: w00t  # casimir
    sub-key: sub-value  # comment 3
    my-sub-key-name-is-longuer-than-yours: 1  # sentinel vs superman

實際輸出是:

list-of-maps:
  - part_no: A4786  # comment 1
    part_henon: mouhaha # you're not funny
  - part_yes: A21  # also a comment here
    part_iculier: partenaire # I don't always understand how it works
    part_third: key # komment
list-only:
  - first # comment 2
  - third # I have a comment too
  - second # what?
simple-map:
  what-are-you-waiting-for: christmas?  # duke nukem rulez
  jingle: bels # not christmas yet
map-of-maps:
  key:
    another-sub-key: w00t  # casimir
    sub-key: sub-value # comment 3
    my-sub-key-name-is-longuer-than-yours: 1 # sentinel vs superman

所以似乎:

  • 對於 CommentedMaps,第一個鍵的注釋在 # 前有兩個空格,但與 CommentedMap 的其他鍵關聯的其他注釋沒有
  • 對於 CommentedSeqs,# 前總是有一個空格

我錯過了什么嗎?

附加信息:

順便說一下,一個更簡單的例子給出了相同的輸出/行為:

"""Test comments on a very simple CommentedMap."""
import sys
import ruamel.yaml


comment_column = None
insert = ruamel.yaml.comments.CommentedMap()
insert["test"] = "asdf"
insert.yaml_add_eol_comment("Test Comment!", "test", column=comment_column)
insert["second-key"] = "yop"
insert.yaml_add_eol_comment("Another comment", "second-key", column=comment_column)

yaml = ruamel.yaml.YAML()
yaml.dump(insert, sys.stdout)

輸出:

test: asdf  # Test Comment!
second-key: yop # Another comment

免責聲明:

  • 非常感謝ruamel.yaml的作者,它是一個很棒的庫……感謝您觀看有關庫的 SO 問題
  • 我根本沒有假裝是一個優秀的 Python 開發人員,所以如果我的代碼質量不好,請原諒我

在映射的第一個注釋上有兩個空格是一個錯誤。 如果您不指定列,則該列會根據前面的鍵進行猜測。 對於不可用的映射中的第一個鍵值對,這會導致代碼路徑略有不同。

修復該錯誤對您沒有幫助,您必須提供自己的yaml_add_eol_comment ,它總是會增加一個額外的空間:

import sys
import ruamel.yaml


yaml = ruamel.yaml.YAML()
yaml.indent(mapping=2, sequence=4, offset=2)
inp = """
list-of-maps:
  - part_no: A4786 # comment 1
    part_henon: mouhaha    # you're not funny
  - part_yes: A21 # also a comment here
    part_iculier: partenaire # I don't always understand how it works
    part_third: key # komment
list-only:
  - first # comment 2
  - third # I have a comment too
  - second # what?
simple-map:
  what-are-you-waiting-for: christmas? # duke nukem rulez
  jingle: bels # not christmas yet
map-of-maps:
  key:
    another-sub-key: w00t # casimir
    sub-key: sub-value # comment 3
    my-sub-key-name-is-longuer-than-yours: 1 # sentinel vs superman
"""

data = yaml.load(inp)


def my_add_eol_comment(self, comment, key=ruamel.yaml.comments.NoComment, column=None):
    org_col = column
    if column is None:
        try:
            column = self._yaml_get_column(key)
        except AttributeError:
            column = 0
    if comment[0] != '#':
        comment = '# ' + comment
    if org_col != 0:  # only do this if the specified colunn is not the beginning of the line
        if comment[0] == '#':
            comment = ' ' + comment
            column = 0
    start_mark = ruamel.yaml.error.CommentMark(column)
    ct = [ruamel.yaml.tokens.CommentToken(comment, start_mark, None), None]
    self._yaml_add_eol_comment(ct, key=key)

ruamel.yaml.comments.CommentedBase.yaml_add_eol_comment = my_add_eol_comment


def process_comments(data, column=None):
    if isinstance(data, dict):
        if data.ca:
            if data.ca.items:
                for key in data.ca.items.keys():
                    if data.ca.items[key][2]:
                        comment = data.ca.items[key][2].value.replace("\n", "")
                        data.yaml_add_eol_comment(comment, key, column=column)
        for k, v in data.items():
            process_comments(k, column=column)
            process_comments(v, column=column)
    elif isinstance(data, list):
        if data.ca:
            if data.ca.items:
                for key in data.ca.items.keys():
                    if data.ca.items[key][0]:
                        comment = data.ca.items[key][0].value.replace("\n", "")
                        data.yaml_add_eol_comment(comment, key, column=column)
        for elem in data:
            process_comments(elem, column=column)

process_comments(data, column=None)
yaml.dump(data, sys.stdout)

這使:

list-of-maps:
  - part_no: A4786  # comment 1
    part_henon: mouhaha  # you're not funny
  - part_yes: A21  # also a comment here
    part_iculier: partenaire  # I don't always understand how it works
    part_third: key  # komment
list-only:
  - first  # comment 2
  - third  # I have a comment too
  - second  # what?
simple-map:
  what-are-you-waiting-for: christmas?  # duke nukem rulez
  jingle: bels  # not christmas yet
map-of-maps:
  key:
    another-sub-key: w00t  # casimir
    sub-key: sub-value  # comment 3
    my-sub-key-name-is-longuer-than-yours: 1  # sentinel vs superman

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM