有没有办法用 ruamel.yaml 对 dump() 应用转换?

Is there a way to apply transformations on dump() with ruamel.yaml?

上下文

我正在使用 ruamel.yaml (0.17.21) 自动 inject/update 将嵌套对象添加到现有 YAML 文档的集合中。

所有这些文档的最大行长度为 120 个字符,由 linter 强制执行。 我希望能够通过在 YAML 实例上设置 width 属性来保留此格式化规则。然而,在实践中,诸如 URL 之类的牢不可破的词在被转储回输出流时最终会超出 120 个字符的限制。

例如,以下代码重新格式化输入,如下面的差异所示,尽管我没有对其进行任何修改:

from ruamel.yaml import YAML
import sys

yaml = YAML()
yaml.width = 120

input = yaml.load('''\
arn:
  description: ARN of the Log Group to source data from. The expected format is documented at
     https://docs.aws.amazon.com/service-authorization/latest/reference/list_amazoncloudwatchlogs.html#amazoncloudwatchlogs-resources-for-iam-policies
''')

yaml.dump(input, sys.stdout)
 arn:
-  description: ARN of the Log Group to source data from. The expected format is documented at
-    https://docs.aws.amazon.com/service-authorization/latest/reference/list_amazoncloudwatchlogs.html#amazoncloudwatchlogs-resources-for-iam-policies
+  description: ARN of the Log Group to source data from. The expected format is documented at https://docs.aws.amazon.com/service-authorization/latest/reference/list_amazoncloudwatchlogs.html#amazoncloudwatchlogs-resources-for-iam-policies

问题

有没有一种方法可以在不实现我自己的 Emitter 的情况下影响 dump() 的结果,例如手动验证生成的行不会溢出所需的最大行长度,然后换行如果是这样的话我自己?

普通标量的发射器发生了一些奇怪的事情,那就是 旧的(继承的)代码,因此可能需要一些时间来修复(不破坏其他东西。

我认为您可以通过以下方式以编程方式更正这些问题 WrapToLong class 传递给变换参数。我在这里使用 class 所以你不需要 使用一些全局变量来获取执行实际工作的例程的宽度:

from ruamel.yaml import YAML
import sys

yaml = YAML()
yaml.width = 120

input = yaml.load('''\
arn:
  description: ARN of the Log Group to source data from. The expected format is documented at
     https://docs.aws.amazon.com/service-authorization/latest/reference/list_amazoncloudwatchlogs.html#amazoncloudwatchlogs-resources-for-iam-policies
''')

class WrapToLong:
    def __init__(self, width, indent=2):
        self._width = width
        self._indent = indent

    def __call__(self, s):
        res = []
        for line in s.splitlines():
            if len(line) > self._width and ' ' in line:
                idx = 0
                while line[idx] == ' ':
                    idx += 1
                line, rest = line.rsplit(' ', 1)
                res.append(line)
                res.append(' ' * (idx + self._indent) + rest)
                continue
            res.append(line)
        return '\n'.join(res) + '\n'

yaml.dump(input, sys.stdout, transform=WrapToLong(yaml.width))

给出:

arn:
  description: ARN of the Log Group to source data from. The expected format is documented at
    https://docs.aws.amazon.com/service-authorization/latest/reference/list_amazoncloudwatchlogs.html#amazoncloudwatchlogs-resources-for-iam-policies

您可以使用折叠标量(使用 >-),它们将换行符保留在 ruamel.yaml 中,但您需要更新 您所有的 YAML 文件(以编程方式),如果 URL 之前的文本发生变化,您将无法轻松更新加载的字符串,因为这会改变字符串折叠的位置。