【问题标题】:Replace updated version strings in files via Python通过 Python 替换文件中更新的版本字符串
【发布时间】:2019-07-19 08:43:40
【问题描述】:

我想用Python替换foopkg/__init__.py中的版本字符串:

__version__ = "0.1.3"

…在setup.py:

#!/usr/bin/env python
from os.path import join
from setuptools import find_packages, setup


version = "0.1.3"

entry_points = {
    "console_scripts": [
        "say-foo = fooproj.foo:foo"
    ]
}

[...]

这两个文件的绝对路径和新版本号分别通过file_pathnew_version 参数传递给以下函数:

def update_version_strings(file_path, new_version):
    VERSION_REGEX = re.compile(
        r"(^(__)?version(__)?\s*=\s*\")(?P<version>\d+\.\d+\.\d+)\"$"
    )
    with open(file_path, "r+") as f:
        content = f.read()
        f.seek(0)
        f.write(
            re.sub(
                VERSION_REGEX,
                lambda match: '{}{}"'.format(match.group(1), new_version),
                content,
            )
        )
        f.truncate()

通过以下方式调用此函数:

update_version_strings("/path/to/foopkg/__init__.py", "0.1.4")

... 将foopkg/__init__.py 中的版本号行正确替换为__version__ = "0.1.4",但update_version_strings("/path/to/setup.py", "0.1.4") 不会对setup.py 文件产生任何更改。

我想问题出在VERSION_REGEXlambda match 指令的某种组合上。诚然,我并不精通正则表达式,而且几乎可以肯定地以一种不太理想的方式做到了这一点。

替换这两种不同版本字符串格式并将更改写入各自文件的最佳方法是什么?

加分:如果还支持单引号样式,那就太好了,这样__version__ = '0.1.3'version = '0.1.3' 字符串中的版本号也将被正确替换。 (^_^)

【问题讨论】:

  • 您这样做是为了发布 sdist/bdist 并在每个版本上更新版本吗?
  • 我正在使用 Poetry 来增加 pyproject.toml 中的版本,但我也想增加其他文件中的版本字符串,因为 Poetry 目前不能这样做。我知道有许多 CLI 工具可以增加版本字符串,但是对于这个用例,我想避免添加另一个依赖项,而是更喜欢在现有代码环境中增加这些额外的版本字符串。

标签: python regex string replace


【解决方案1】:

两种不同版本的字符串格式使用以下方法(也包括单引号/双引号):

def update_version_strings(file_path, new_version):
    version_regex = re.compile(r"(^_*?version_*?\s*=\s*['\"])(\d+\.\d+\.\d+)")
    with open(file_path, "r+") as f:
        content = f.read()
        f.seek(0)
        f.write(
            re.sub(
                version_regex,
                lambda match: '{}{}'.format(match.group(1), new_version),
                content,
            )
        )
        f.truncate()

【讨论】:

  • 这个功能和预期的一样,但又发现了另一个问题:只有当版本字符串是文件的第一行时,版本字符串才会被替换。有时确实如此(如目前在__init__.py 中),但在诸如setup.py 之类的文件中,版本字符串行之前和之后还有许多其他行。我已经在我的原始问题中更新了setup.py 的示例内容以反映这一点。您可能知道如何修改此函数,以便适当更新包含版本字符串的 任何 行吗?
【解决方案2】:

在多行文件中,匹配行首/尾的关键是re.Mre.MULTILINE 指令。以下函数在可能有多行的文件中替换 version = "0.1.3"__version__ = '0.1.3' 字符串格式的版本号(包括单引号和双引号):

def update_version_strings(file_path, new_version):
    version_regex = re.compile(r"(^_*?version_*?\s*=\s*['\"])(\d+\.\d+\.\d+)", re.M)
    with open(file_path, "r+") as f:
        content = f.read()
        f.seek(0)
        f.write(
            re.sub(
                version_regex,
                lambda match: "{}{}".format(match.group(1), new_version),
                content,
            )
        )
        f.truncate()

【讨论】:

    猜你喜欢
    • 2022-01-17
    • 2016-04-01
    • 1970-01-01
    • 1970-01-01
    • 2017-09-04
    • 2018-08-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多