Poetry插件,用于从__version__变量或Git标签动态提取包版本。
项目描述
Poetry版本插件
Poetry插件,用于动态提取包版本。
它可以读取文件__init__.py
中的版本
# __init__.py
__version__ = "0.1.0"
或者,它可以从git tag
读取版本,该标签通过GitHub发布或
$ git tag 0.1.0
🚨 请注意,这处于alpha阶段。请阅读下面的警告。
何时使用
这主要用于如果您正在构建一个供他人使用的包库,并且您想在不同于pyproject.toml
的位置设置版本,但您仍然想保持一个单一的事实来源。
在其他用例中,如使用Poetry管理本地应用程序环境,它将不会很有帮助。
如何使用
确保您有Poetry版本1.2.0a1
或更高版本。如果您还没有安装它,请阅读下面的说明。
安装Poetry版本插件
将此插件安装到您的Poetry
$ poetry plugin add poetry-version-plugin
--> 100%
在初始化文件中设置版本号
将您的包版本设置在文件 __init__.py
中,例如
from .main import do_awesome_stuff, AwesomeClass
__version__ = "0.2.3"
然后编辑您的 pyproject.toml
文件,包含以下部分
[tool.poetry-version-plugin]
source = "init"
接下来,构建您的项目。输出将类似
$ poetry build
Using __init__.py file at my_awesome_package/__init__.py for dynamic version
Setting package dynamic version to __version__ variable from __init__.py: 0.1.9
Building my-awesome-package (0.1.9)
- Building sdist
- Built my-awesome-package-0.1.9.tar.gz
- Building wheel
- Built my-awesome-package-0.1.9-py3-none-any.whl
在Git标签中设置版本号
或者,要从Git标签提取版本号,添加一个部分
[tool.poetry-version-plugin]
source = "git-tag"
然后创建一个git标签,例如
$ git tag 0.1.3
在这种情况下,当构建您的项目时,输出将类似
$ poetry build
Git tag found, setting dynamic version to: 0.1.3
Building my-awesome-package (0.1.3)
- Building sdist
- Built my-awesome-package-0.1.3.tar.gz
- Building wheel
- Built my-awesome-package-0.1.3-py3-none-any.whl
pyproject.toml
中的版本号
目前(2021-05-24)Poetry需要在 pyproject.toml
中配置 version
,即使您使用此插件也是如此。
当使用此插件时,该 version
配置不会使用,但Poetry仍然要求它在 pyproject.toml
中存在。
为了更明显地表明您没有使用该 version
,您可以将其设置为 0
。
[tool.poetry]
name = "my-awesome-package"
version = "0"
这样,您将更容易注意到插件是否未安装,因为它将显示您正在构建一个版本为 0
的包,而不是动态设置的版本。
一个示例 pyproject.toml
一个简短的最小示例 pyproject.toml
可能看起来像
[tool.poetry]
name = "my-awesome-package"
version = "0"
description = ""
authors = ["Rick Sanchez <rick@rick-citadel.com>"]
readme = "README.md"
[tool.poetry.dependencies]
python = "^3.6"
[build-system]
requires = ["poetry-core"]
build-backend = "poetry.core.masonry.api"
[tool.poetry-version-plugin]
source = "init"
原因
默认情况下,Poetry期望您在 pyproject.toml
中设置包版本。在大多数情况下,这都会工作。
但想象一下,您希望将包的版本暴露在 __version__
变量中,以便用户可以执行类似以下操作
import my_awesome_package
print(my_awesome_package.__version__)
您可以手动编写 __version__
变量,并自行处理与 pyproject.toml
之间的同步,这非常 容易出错。
目前官方的解决方案是不重复值是使用 importlib.metadata
。
但是,该模块仅在Python 3.8及以上版本中可用。因此,对于Python 3.7和3.6,您必须将作为包依赖项的回滚版本安装
[tool.poetry.dependencies]
importlib-metadata = {version = "^1.0", python = "<3.8"}
但是,当它们发布回滚版本的每个新版本时(目前为4.0.1
),您必须更新它(或不必更新)。并且您的用户必须手动处理与任何其他依赖 importlib-metadata
的包之间的冲突,这可能有很多,因为许多包可能正在执行相同的操作(我处理过这种情况)。
另一种选择是不在 pyproject.toml
中对您的 importlib-metadata
的任何版本范围进行固定,并寄希望于最好。
然后,您的 __init__.py
必须包含使用它的代码,如下所示
# I don't want this extra complexity 😔
# And it doesn't work in Docker 🐋
try:
import importlib.metadata as importlib_metadata
except ModuleNotFoundError:
import importlib_metadata
__version__ = importlib_metadata.version(__name__)
但是,这段代码增加了您代码中的额外复杂性和逻辑,在每个包中都需要。
🚨 此外,这只在您的包安装在Python环境中时才有效。例如,如果只是将代码放入一个 容器 中,这对于Web应用和分布式系统来说很常见,那么它将不起作用。
此插件如何解决这个问题
使用此插件,您的包不依赖于 importlib-metadata
,因此用户不需要处理冲突或额外的依赖项。
相反,需要安装此插件的构建系统(Poetry)。
这样可以避免您方面的额外代码复杂性、用户之间的依赖项冲突以及支持其他用例,例如直接在容器内部复制的代码。
从Git标签获取版本号
此外,此插件还可以从Git标签中提取版本号。
因此,您只需要在Git标签(例如GitHub发布)中创建每个版本,而不是将其写入代码。
然后,在持续集成(例如GitHub Actions)上构建包。然后此插件将从这个Git标签中获取包的版本。
安装Poetry 1.2.0a1
为此插件能够工作,您需要Poetry版本 1.2.0a1
或更高版本。
您很可能已经安装了Poetry 1.1.x
。
第一步是卸载它
$ curl -sSL https://raw.githubusercontent.com/python-poetry/poetry/master/get-poetry.py -O
--> 100%
$ python get-poetry.py --uninstall
--> 100%
然后使用新安装程序安装新的 Poetry
$ curl -sSL https://raw.githubusercontent.com/python-poetry/poetry/master/install-poetry.py -O
--> 100%
$ python install-poetry.py --preview
--> 100%
🔍 注意,新安装程序文件的名称是 install-poetry.py
而不是 get-poetry.py
。另外,目前,您需要设置 --preview
才能安装 alpha 版本 1.2.0a1
。
您可以使用以下方法检查是否安装成功:
$ poetry --version
Poetry (version 1.2.0a1)
init 文件中的版本支持
当在您的 __init__.py
中使用 __version__
变量时,您可以在该文件中包含更多逻辑,导入模块,并在该变量的声明上方和下方进行更多操作。
但是,其值必须是字面字符串,例如
___version___ = "0.2.0"
...而不是调用一个函数或类似的东西。
该变量必须是顶层变量,因此不能位于 if
语句或类似的语句中。
这在您的 __init__.py
中都是可以正常使用且受支持的
# __init__.py
# This is all valid 👍✅
from .main import do_awesome_stuff, AwesomeClass
awesome = AwesomeClass()
# Some comment explaining why this is commented out
# __version__ = "1.0.0"
__version__ = "0.2.3"
if __name__ == "__main__":
awesome.run()
以下示例是有效且受支持的,并且它包括
- 导入
- 其他对象和变量
- 注释
- 注释中相同的字符串
__version__
- 周围的 if 块
但是,这不受支持
# 🚨 Not supported
if 2 == 2:
__version__ = "0.1.0
而且,这也不受支持
# 🚨 Not supported
def get_version():
return "0.2.0"
__version__ = get_version()
插件的工作方式
当 Poetry 在构建包时运行插件,并在创建“包发行版”(例如,wheel)之前设置版本。
版本变量的工作方式
如果您在 pyproject.toml
中的 packages
配置中声明了包(单个包),则插件将使用该包的 __init__.py
来查找 __version__
变量。
如果您没有 packages
配置,则插件将假设您有一个名为您项目的单个包,但在模块版本中(将 -
替换为 _
)。因此,如果您的包是 my-awesome-project
,则插件将使用位于 my_awesome_project/__init__.py
的文件来查找 __version__
变量。
如果您使用 poetry new
命令创建新项目,则此文件结构是默认的,因此应该按预期工作。✨
插件内部的工作方式是通过解析 __init__.py
文件。使用 ast
标准模块读取 Python 的“抽象语法树”,并提取字符串的字面值。因此,它不会在 __init__.py
中执行代码,而只是将其作为 Python 代码进行读取。
插件不会尝试导入和执行该 __init__.py
文件,因为这可能需要额外的计算、外部依赖项等。它也不会尝试使用正则表达式提取 __version__
,因为这可能会出错,例如,如果代码中某个地方(在注释或字符串中)有另一个 __version__
。
警告
🚨 请注意,这是在 alpha 阶段。支持插件的 Poetry 1.2.0a1
已于 2021-05-21 发布。我在 3 天后(2021-05-24)开始编写此插件。
在 Poetry 或此插件中可能会出现错误。因此,请在完全采用它用于敏感系统之前仔细尝试并测试它。
其工作方式可能会改变,具体的配置可能会改变。
此外,如果您发现以下部分不够直观
[tool.poetry-version-plugin]
source = "init"
并且
[tool.poetry-version-plugin]
source = "git-tag"
请告诉我哪种替代配置对您来说更有意义,更直观。
👍 好消息是,假设您正在构建用于随后上传到 PyPI 以供用户下载和使用的包,如果出现问题,最坏的情况是您无法构建新版本,直到问题得到解决或更改。但是,您的用户不应该受到影响。
发行说明
最新更改
0.1.3
- ✨ 改进了日志记录,添加了插件名称前缀。由 @tiangolo 提交的 PR #6。
- 🔧 更新 pyproject 元数据。PR #5 由 @tiangolo 提交。
- ✅ 修复覆盖率。PR #4 由 @tiangolo 提交。
- 📝 改进文档。PR #3 由 @tiangolo 提交。
- 🐛 修复 CI 测试。PR #1 由 @tiangolo 提交。
- 👷 修复 Latest Changes 动作,将分支设置为 main。PR #2 由 @tiangolo 提交。
许可证
本项目受 MIT 许可协议约束。
项目详情
poetry-version-plugin-dontuse-0.1.4.tar.gz 的哈希值
算法 | 哈希摘要 | |
---|---|---|
SHA256 | bf182997575af3b6eff74316e35e88d2f3ac40fce576cdc81c8c462b8d42979c |
|
MD5 | ba2370ca10e66be7f68f7b188d89ba71 |
|
BLAKE2b-256 | 2027ff22a1a154c635e0072fd562683d7a42c75b127327dee9c967ebcf2e305b |
poetry_version_plugin_dontuse-0.1.4-py3-none-any.whl 的哈希值
算法 | 哈希摘要 | |
---|---|---|
SHA256 | cec10e0c02175b644de6610854edd4ba2b37203053b86482aec8c7bc94b64b38 |
|
MD5 | 2658aaa3341b8b814d455a04b6cfbe83 |
|
BLAKE2b-256 | e2b30004626e6010d5a5bd06f5536e9226951ec671493178159b1981ae9fb231 |