跳转到主要内容

基于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,现在可能无法更改。

  1. 部分名称非常宽松。 [[x]]yy 是一个合法的部分行,生成的部分名称是 [x。这里的 yy 总是允许的(我们虽然保留它在树中),即使关闭了 inline_comments
  2. \r(回车)被视为空白,但不是行终止符。这是 str.splitlines(True)list(io) 之间行为的不同之处 -- configparser 使用后者。
  3. \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 (16.0 kB 查看哈希)

上传时间

构建分发

imperfect-0.3.0-py3-none-any.whl (13.4 kB 查看哈希)

上传时间 Python 3

支持者