replacement是一个python实用程序,它解析yaml模板并输出文本。

replacement的Python项目详细描述


替换Build Status

replacement是一个python实用程序,它解析yaml模板并输出文本。

安装

pip3 install replacement

或者,如果您使用nix

nix-env --install -A 'nixpkgs.python36Packages.replacement'

简介

注:此处给出的示例在 tests

template是包含replacement对象的yaml文件。

替换对象包含blocks的列表。

一。基本模板

模板:

---# simplistic template example# tests/hello.yamlreplacement:-text:textinput:hello world...

使用replacement

执行模板
$ replacement -t tests/hello.yaml
hello world

块总是以directive开头,它指定:

  • 块将yield的数据类型,例如textdict
  • 输入数据类型,例如fileyaml

在上面的块中,text: text是指令; 它指定块接受text输入并产生text输出。

2.读取文件

文件hello.out

hello world
---# read from file# tests/file.yamlreplacement:-text:fileinput:hello.out...
$ replacement -t tests/file.yaml
hello world

注意:

  • 上面块中的指令是text: file; 这意味着:“产生文本,从文件中输入”。
  • 要读取的文件名使用input键; 在第一个示例中,input用于存储文本输入。
  • 文件路径相对于模板的路径。

间歇:模式

所有替换指令的架构都包含在schema.yaml中。

下面是一个片段,显示块的directiveinput部分:

---### format of a block##block:-yield:inputType# this is a directiveinput:inputVal### definition of schema elements##schema:# 'yield' : what to output (how to format output)yield:-text  # text:a list of newline-separated strings-dict# a dictionary of key-value pairs-meta  # output nothing:set a metadata (substitution dictionary) variable# 'input' : where to source datainputType:# we can input everything we output (see 'yield' above)-text-dict-meta# a key-value pair retrieved from substitutions dictionary# we can also input from other sources-file# open a file on disk-eval# python3 eval() statement-func# import and then call call a function-exec# subprocess execution (usually bash)inputVal:input_specific...

三。元数据和替换

meta指令指定应该插入块的输出 进入“替换字典”(又名:meta)。

  • 这意味着输入必须是有效的字典
  • 替换将解析yaml或json(它是yaml的一个子集)

proc关键字指定应该处理块输出 (字符串替换)。 有效的proc指令是:

  • formatstr.format()
  • substitutestring.Template().substitute()
  • safe_substitutestring.Template().safe_substitute()
---# metadata# tests/metadata.yamlreplacement:# parse 'input' and insert the resulting dictionary into 'meta'-meta:dict# metadata may be given as an objectinput:version:1.1tag:my_awesome_tag-meta:text# metadata may be given as text which can be parsed as valid YAMLinput:|---message: hello world...-meta:text# metadata may also be given as JSONinput:|{ "hi": 5 }# use 'proc' to specify that 'str.format(**meta)' should be run on output-text:textproc:formatinput:|v{version} tag "{tag}"-text:textproc:substituteinput:|message $message-text:textproc:safe_substituteinput:|hi $hithis value may not exist - $nonexistent...
$ replacement -t tests/metadata.yaml
v1.1 tag "my_awesome_tag"
message hello world
hi 5
this value may not exist - $nonexistent

元数据也可以从文件中读取。

文件a.json

{"hello":"world","hi":5,"list":[1,2,3,4]}
---# metadata# tests/meta_file.yamlreplacement:# parse file, inserting result into metadata dictionary-meta:fileinput:a.json# string substitution with 'proc'-text:textproc:formatinput:|hello {hello}hi {hi}list {list}...
$ replacement -t tests/meta_file.yaml
hello world
hi 5
list [1, 2, 3, 4]

3A.使用key

的值->;字典
---# insert contents of file as metadata# tests/file_as_meta.yamlreplacement:-text:dictinput:# produces {"hello": "hi"}-dict:textkey:helloinput:|hi-dict:filekey:contentsinput:hello.out-meta:filekey:datainput:prep.out-dict:dictprep:substituteinput:also:$data-meta:filekey:largefileinput:recurse.out-dict:dictprep:formatinput:hello:worldhi:|{largefile}...
---
hello: hi
contents: hello world
also: hello world
hi: |-
  recursed inline
  v1.1 tag "my_awesome_tag"
  message hello world
  hi 5
  this value may not exist - I exist I promise!
...

四。嵌套

  1. 块按顺序执行,并且可以嵌套。
    • 嵌套块可以扩展/改变meta,这将由 以后的块或子块,但不是父块。
---# nesting and dictionaries# tests/nesting.yamlreplacement:# parse 'input' and insert the resulting dictionary into 'meta'-meta:dictinput:version:1.1# same thing, but parse *text* input, instead of a dictionary-meta:textinput:|# note the '|'---tag: my_awesome_tag...# use 'proc' to specify that 'str.format(**meta)' should be run on output-text:textproc:formatinput:|v{version} tag "{tag}"-text:textinput:# metadata additions/changes seen by later blocks and any children,# but seen outside this list-meta:dictinput:version:1.0-text:textproc:formatinput:|#v{version} tag "{tag}" (version clobbered in inner scope)-text:fileinput:hello.out# contains 'hello world'-text:textproc:formatinput:|outer still v{version}...
$ replacement -t tests/nesting.yaml
v1.1 tag "my_awesome_tag"#v1.0 tag "my_awesome_tag" (version clobbered in inner scope)
hello world
outer still v1.1

5个。预处理

也可以对块本身的值执行替换 在分析它之前。 使用关键字prep,其语义与proc(上)相同:

---# preprocessing# tests/prep.yamlreplacement:-meta:dictinput:filename:hello.out# preprocessing will substitute {filename} before evaluating 'file' input-text:fileprep:formatinput:|{filename}...
$ replacement -t tests/prep.yaml
hello world

6.访问pythoneval

---# use of eval# tests/an_eval.yamlreplacement:# 'eval' returning a dictionary that can me appended to 'meta'-meta:evalinput:|{"hello": 5 + 1}-text:textprep:formatinput:|hello {hello}# eval returning a scalar value-text:evalprep:formatinput:|{hello}**3...
$ replacement -t tests/an_eval.yaml
hello 6216

7号。Pythonexec

有时操作运行时环境是有利的。

在下面的例子中,它被用来导入一个模块 由对eval的子序列调用所需要。

---# use of eval with an exec statement to execute an import call# tests/eval_exec.yamlreplacement:-meta:execinput:|global IPv4Networkfrom ipaddress import IPv4Network-meta:evalinput:|{'gateway': str([h for h in IPv4Network('192.168.1.0/24').hosts()][-1])}-text:textprep:formatinput:|my gateway is {gateway}...
$ replacement -t tests/eval_exec.yaml
my gateway is 192.168.1.254

注意:pythonexec非常强大, 请避免以特权用户身份运行replacement

8个。导入和函数执行

func输入指令可用于查找和调用外部函数 (参考demo.py):

---# function execution# tests/func.yamlreplacement:# run a function returning a dictionary, and merge that into 'meta'-meta:funcargs:existing:{'original':'thesis'}# NOTE that this is sensitive to PYTHONPATHinput:|ret_a_dict ./demo.py-text:textprep:formatinput:|original {original}secret {secret}# run a function returning a dictionary and export return as JSON-text:funcoptions:-json# emit JSON rather than YAML (the default)args:existing:{'original':'thesis'}input:|ret_a_dict ./demo.py# run a function returning an IOStream-text:funcargs:{}# notice non-portable BRAINDEAD python dot.notation# ... will break if 'replacement' (the script) is MOVED vis-a-vis demo.py# (of OF COURSE the CWD is blithely ignored ... why would ANYONE use it LOL)# TLDR: use the '[symbol] [path]' notation in the preceding exampleinput:|tests.demo.ret_a_stream# A function returning a list of lines of text# (using the proper, cleaner import strategy)-text:funcargs:an_arg:["question"]input:|ret_a_list ./demo.py# a static function inside a class-text:funcinput:|aClass.invented_list ./demo.py
$ replacement -t tests/func.yaml
original thesis
secret 42{"secret": 42, "original": "thesis"}1. hello
2. world
42
meaning
question
hello
from
staticmethod

9号。递归

或者,我如何学会不再担心,让模板导入其他模板。

---# recursion (nested 'replacement' templates)# tests/recurse.yamlreplacement:# parse a 'replacement' template inline-replacement:textinput:|---replacement:- text: textinput: |recursed inline...-meta:dictinput:nonexistent:"IexistIpromise!"# parse a replacement template from a file# NOTE *relative* path)# NOTE our 'meta' dictionary is propagated to child replacement being parsed-replacement:fileinput:metadata.yaml...
$ replacement -t tests/recurse.yaml
recursed inline
v1.1 tag "my_awesome_tag"
message hello world
hi 5
this value may not exist - I exist I promise!

注释

  1. 此文档本身是作为模板构建的,因此 在.yaml测试和.out结果中,与tests保持同步。 目录。 见README.template.yamlgen_readme.sh

项目待办事项

项目待办事项列表

  1. 子流程执行和输出捕获

  2. 接受来自stdin的模板,而不仅仅是模板文件

  3. 包装:

    • 正确的测试运行程序(可能是tox?)
    • 添加测试运行程序所有的版本
  4. dependency output命令:运行所有预处理并输出 文件依赖项。 用于生成文件。

  5. 正式表达the schema并为其编写验证代码。

欢迎加入QQ群-->: 979659372 Python中文网_新手群

推荐PyPI第三方库


热门话题
在EclipseIDE中设计JavaSwingGUI的最简单方法是什么?   用java显示字符串的第二行   java如何编写一个自定义的crudepository方法(@Query)来过滤我的案例中的结果   如何在Java中解析字符串?   java如何使两个数组随机相等   java为什么hang()方法只执行一次?   java图像缩小问题   java将按键从小程序“转发”到JFrame   错误处理是否适合捕获java。多线程应用程序中的lang.ExceptionInInitializerError?   JAVAlang.IllegalArgumentException:文件不包含有效的私钥:/Users/x/application。钥匙   为什么我们使用动态代理   java VBA填充网页文本框   在方法调用中间没有中断的java IntLIJ思想行包装   java WebDriver driver=新的ChromeDriver(选项);显示构造函数ChromeDriver(ChromeOptions)未定义