基于CST的configparser配置编辑器
项目描述
Imperfect
这是一个用于对现有的configparser兼容的ini文件进行自动编辑的模块。它的工作方式类似于CST,解析为节点树,然后可以对其进行编辑并写回,同时保留空白和注释。
快速入门
(在测试套件中作为 test_example_from_readme
进行测试)
假设你在 setup.cfg
中有以下内容
[metadata]
# the package name
name = imperfect
# slurp the readme
long_description = file: README.md
[options]
packages = imperfect
并且你想在 [metadata]
中编辑 long_description_content_type
设置,但不在意它放在哪里。默认是放在最后。
import difflib
import imperfect
import io
with open("setup.cfg") as f:
data = f.read()
conf: imperfect.ConfigFile = imperfect.parse_string(data)
conf.set_value("metadata", "long_description_content_type", "text/markdown")
print(conf.text)
如果你想要控制顺序,并希望它紧接在 long_description
之后呢?现在有了diffing和更多内部功能...
import difflib
import imperfect
import io
with open("setup.cfg") as f:
data = f.read()
conf: imperfect.ConfigFile = imperfect.parse_string(data)
metadata_section = conf["metadata"]
# Ignoring some whitespace for now, this looks like
# long_description_content_type = text/markdown\n
# [ entry ]
# [ key ][eq][ value ]
value = imperfect.ValueLine(
whitespace_before_text='',
text='text/markdown',
whitespace_after_text='',
newline='\n',
)
new_entry = imperfect.ConfigEntry(
key="long_description_content_type",
equals="=",
value = [value],
whitespace_before_equals=" ",
whitespace_before_value=" ",
)
for i, entry in enumerate(metadata_section.entries):
if entry.key == "long_description":
metadata_section.entries.insert(i+1, new_entry)
break
print(moreorless.unified_diff(data, conf.text, "config.cfg", end=""))
with open("setup.cfg", "w") as f:
f.write(conf.text)
# or
with open("setup.cfg", "w") as f:
conf.build(f)
关于空白的说明
遵循configobj使用的约定,空白通常积累并存储在其后的节点上。这对于添加条目来说做得相当不错,但在删除它们时可能会有意想不到的后果。例如,
[section1]
# this belongs to k1
k1 = foo
# this belongs to k2
k2 = foo
# k3 = foo (actually belongs to the following section)
[section2]
在 section1
的末尾插入会放在k2和k3注释之间。删除 section2
也会删除被注释掉的 k3
。
我欢迎任何改进这一点的想法。
关于格式的说明
目标是尽可能与 RawConfigParser
兼容,包括保留一些已经存在十年的bug,现在可能无法更改。
- 部分名称非常宽松。
[[x]]yy
是一个合法的部分行,生成的部分名称是[x
。这里的yy
总是允许的(我们虽然保留它在树中),即使关闭了inline_comments
。 \r
(回车)被视为空白,但不是行终止符。这是str.splitlines(True)
和list(io)
之间行为的不同之处 -- configparser 使用后者。\t
计算为单个空白。
支持的解析选项
Option Default Imperfect supports
allow_no_value False only False
delimiters =,: only =,:
comment_prefixes #,; only #,;
empty_lines_in_values True True (False is very close to working)
测试
我们使用hypothesis生成合理的ini文件,并测试所有RawConfigParser可以接受的文件,以确保我们也能接受,并具有相同的键/值,并且可以往返。
目前仅在文本模式下发生。
如果您想测试对您文件的支持,请尝试 python -m imperfect.verify <文件名>
为什么不...
configobj
有完全不同的行续行方法- 我不知道还有其他目的是为了保留空白字符的
许可证
Imperfect 是 Tim Hatch 的版权所有,并按照 MIT 许可证授权。我在此仓库中以开源许可证提供代码。这是我的个人仓库;您收到的我的代码的许可证来自我,而不是我的雇主。有关详细信息,请参阅 LICENSE
文件。
项目详情
下载文件
下载您平台的文件。如果您不确定选择哪个,请了解有关 安装包 的更多信息。
源分发
构建分发
imperfect-0.3.0.tar.gz 的哈希
算法 | 哈希摘要 | |
---|---|---|
SHA256 | c7d89d9d0c2d8f6ea2b8e7ae3e5ebf3410ea1f092cfdc18355c21af483e7b5c9 |
|
MD5 | 11b71151fafd103874c803205f23a1f2 |
|
BLAKE2b-256 | ca33a768bd7628a30d729d656739db5d8b92542de5bb596c9150c37d8a561c42 |
imperfect-0.3.0-py3-none-any.whl 的哈希
算法 | 哈希摘要 | |
---|---|---|
SHA256 | 212bfbfc435746e64d437e75542416a426c08c78bcd6b1cdb10ef1e5c5a16fce |
|
MD5 | 82c1644e20c48458041bb3f15da398a3 |
|
BLAKE2b-256 | adc1469cc0d9ac261c1c98620d65bed23c69565696963562fd14f1583a116b9b |