PyYaml事件结构中不必要的子键引用和通过主键迭代 [英] Unnecessary quotation of subkey and iteration through primary key in PyYaml event structure

查看:32
本文介绍了PyYaml事件结构中不必要的子键引用和通过主键迭代的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有下一个代码:

import gnupg
import re
import textwrap
from pprint import pprint
import yaml
from yaml.events import *

class AppendableEvents:
  def __init__(self, path, events):
    self.path = path
    self.events = events

  def correct_position(self, levels):
    if len(self.path) != len(levels):
      return False
    for index, expected in enumerate(self.path):
      if expected != levels[index].cur_id:
        return False
    return True

class Level:
  def __init__(self, mode):
    self.mode = mode
    self.cur_id = -1 if mode == "item" else ""

def append_to_yaml(yamlFile, targetFile, items):
  events = []
  levels = []
  with open(yamlFile, 'r') as handle:
    for event in yaml.parse(handle):
      if isinstance(event, StreamStartEvent) or \
         isinstance(event, StreamEndEvent) or \
         isinstance(event, DocumentStartEvent) or \
         isinstance(event, DocumentEndEvent):
        pass
      elif isinstance(event, CollectionStartEvent):
        if len(levels) > 0:
          if levels[-1].mode == "key":
            # we can only handle scalar keys
            raise ValueError("encountered complex key!")
          else:
            if levels[-1].mode == "value":
              levels[-1].mode = "key"
        if isinstance(event, MappingStartEvent):
          levels.append(Level("key"))
        else: # SequenceStartEvent
          levels.append(Level("item"))
      elif isinstance(event, ScalarEvent):
        if len(levels) > 0:
          if levels[-1].mode == "item":
            levels[-1].cur_id += 1
          elif levels[-1].mode == "key":
            levels[-1].cur_id = event.value
            levels[-1].mode = "value"
          else: # mode == "value"
            levels[-1].mode = "key"
      elif isinstance(event, CollectionEndEvent):
        # here we check whether we want to append anything
        levels.pop()
        for item in items:
          if item.correct_position(levels):
            for additional_event in item.events:
              events.append(additional_event)
      events.append(event)
  with open(targetFile, mode="w") as handle:
    yaml.emit(events, handle,line_break=True)

def key(name):
  return ScalarEvent(None, None, (True, True), name)

def literal_value(content):
  return ScalarEvent(None, None, (False, True), content, style="|")

def map(*scalarValues):
  return [MappingStartEvent(None, None, True)] + \
    [ScalarEvent(None, None, (False, True), v, style="|") for v in scalarValues] + \
    [MappingEndEvent()]


gpg = gnupg.GPG(gnupghome='~/.gnupg')
gpg.encoding = 'utf-8'

def ExistingFile():
    with open(creds) as sensitive_data:
        for line in sensitive_data:
            encrypted_value = gpg.encrypt(
                re.sub(r'^( +?|[A-Za-z0-9]|[A-Za]|[0-9])+( +)?' + '=' + '( +)?', '', line, 1),
                recipients="test", always_trust=True)
            if not encrypted_value.ok:
                print(encrypted_value.status, '\n', encrypted_value.stderr)
                break
            line = re.sub(r'^( +)?|( +)?' + '=' + '.*', '', line.rstrip('\n'))
            append_to_yaml(f1, f1, [
              AppendableEvents(["global","app1"], [
                key("app2")] + map(line, encrypted_value.data.decode()))])
                #key(line), literal_value(encrypted_value.data.decode())])])

ExistingFile()

creds 文件的内容是:

Content of creds file is:

1=1
sadsa=ars

f1 文件内容为:

global:
    app1:
      test: |
        -----BEGIN PGP MESSAGE-----
        Version: GnuPG v1
        -----END PGP MESSAGE----- 

在这段代码中,必要的键、子键和值被附加到 yaml 文件中的相应块.

In this code necessary key, subkey and values are being appended to appropriate block in yaml file.

但问题是我在关键方法中传递的值正在被迭代,因此根据creds文件中的内容附加两次或更多次:

But the problem is that value which I pass in key methods is being iterated and thus appends twice or more depending on content in creds file:

global:
    app1:
      test: |
        -----BEGIN PGP MESSAGE-----
        Version: GnuPG v1
        -----END PGP MESSAGE-----     
    app2:
      "1": |
        -----BEGIN PGP MESSAGE-----
        Version: GnuPG v1
        -----END PGP MESSAGE-----
    app2:
      "sadsa": |
        -----BEGIN PGP MESSAGE-----
        Version: GnuPG v1
        -----END PGP MESSAGE-----

子键1"和sadsa"也被附加了双引号.

Also subkeys "1" and "sadsa" are being appended with double quotes.

我想去掉双引号,当我将它与 map 方法结合时,我在 key 方法中传递的那个值只会附加到文件一次.

I want to get rid of double quotes and that value which I pass in key method will be appended to file only one time when I combine it with map method.

所以最终结果将是例如:

So the final result will be for example:

global:
    app1:
      test: |
        -----BEGIN PGP MESSAGE-----
        Version: GnuPG v1
        -----END PGP MESSAGE-----     
    app2:
      1: |
        -----BEGIN PGP MESSAGE-----
        Version: GnuPG v1
        -----END PGP MESSAGE-----
      sadsa: |
        -----BEGIN PGP MESSAGE-----
        Version: GnuPG v1
        -----END PGP MESSAGE-----

注意:使用literal_value 方法的注释行工作得很好,所以我不想破坏它的逻辑,使用map 方法对case 进行更改.

Note: Commented line with literal_value method works pretty fine so I don't want to break it's logic doing changes for case with map method.

推荐答案

首先,请在提问时提供一个最小示例.我从您的代码中删除了 gnupg 内容,因为它与您的问题根本不相关.您有责任仅提供实际代码的相关部分,以便试图帮助您的人无需挖掘不相关的行.

First of all, please provide a minimal example when asking a question. I removed the gnupg stuff from your code because it is not relevant at all to your question. It is your responsibility to provide only relevant parts of your actual code so that people trying to help you do not need to dig through irrelevant lines.

现在,要解决您的问题:您只需要构建适当的输出事件即可.这是一个解决方案(没有 gnupg 的东西):

Now, to solve your question: You simply need to construct the events you output appropriately. Here's a solution (without the gnupg stuff):

def ExistingFile():
  with open(creds) as sensitive_data:
    additions = [key("app2"), MappingStartEvent(None, None, True)]
    for line in sensitive_data:
      encrypted_value = re.sub(r'^( +?|[A-Za-z0-9]|[A-Za]|[0-9])+( +)?' + '=' + '( +)?', '', line, 1)
      line = re.sub(r'^( +)?|( +)?' + '=' + '.*', '', line.rstrip('\n'))
      additions.extend(
        [ScalarEvent(None, None, (True, False), line),
         ScalarEvent(None, None, (False, True), encrypted_value, style='|')])
    additions.append(MappingEndEvent())
    append_to_yaml(f1, f1_mod, [AppendableEvents(["global", "app1"], additions)])

如您所见,我构造键的标量事件与值的标量事件不同,因此值显示为文字标量,键显示为纯标量(不带引号).

As you can see, I construct the scalar event for the key differently from that for the value, so that the value is presented as literal scalar and the key as plain scalar (without quotes).

我也只调用 append_to_yaml 一次,这样 app2 只创建一次.

I also call append_to_yaml only once so that app2 is only created once.

这篇关于PyYaml事件结构中不必要的子键引用和通过主键迭代的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆