使用pyproject.toml时如何仅在一处指定版本?

问题描述 投票:0回答:5

我的包版本在两个地方定义:

  • __version__ = 1.2.3
    mypackage/__init__.py
  • version = "1.2.3"
    pyproject.toml
    (我正在使用诗歌)

每当我更新版本时,我都必须更新这两个版本,这很烦人,而且不干。有没有办法让Python从TOML读取版本,或者让TOML从Python读取版本?

python version dry python-poetry pyproject.toml
5个回答
64
投票

安装项目后 - 无论是通过

poetry install
在可编辑模式下还是通过滚轮 - 您可以通过
importlib.metadata
(对于 Python
importlib_metadata
访问多个元数据) < 3.8).

因此,仅将版本保留在

pyproject.toml

中,并在Python代码中使用它:

import importlib.metadata __version__ = importlib.metadata.version("mypackage")
    

15
投票
这段代码对我有用:

import importlib.metadata __version__ = importlib_metadata.version(__package__ or __name__)
但是,这仅在已经使用 pip 或诗歌

安装了软件包的情况下才有效。 在新版本上(点而不是下划线):

__version__ = importlib.metadata.version(__package__ or __name__)



7
投票

from contextlib import suppress import importlib.metadata from pathlib import Path def extract_version() -> str: """Returns either the version of installed package or the one found in nearby pyproject.toml""" with suppress(FileNotFoundError, StopIteration): with open((root_dir := Path(__file__).parent.parent) / "pyproject.toml", encoding="utf-8") as pyproject_toml: version = ( next(line for line in pyproject_toml if line.startswith("version")) .split("=")[1] .strip("'\"\n ") ) return f"{version}-dev (at {root_dir})" return importlib.metadata.version(__package__ or __name__.split(".", maxsplit=1)[0]) __version__ = extract_version()

给我 
1.2.23

安装的软件包或类似

1.3.42-dev (at /project/location)
    


3
投票
@finswimmer 的回答

的评论中指出的那样,当未安装软件包时,这些方法会破坏 CI 管道等。为了与 @z33k 对这个问题的评论保持一致,一种解决方案是从 pyproject.toml 读取值。

使用 

poetry

作为包管理器,另一个解决方案是使用 poetry-bumpversion 插件,通过 poetry

version
命令来管理版本颠簸。例如,假设您有一个名为
widget
的包,其中
__version__
定义在
widget/__init__.py
中,其值与
pyproject.toml
version
的值相同。使用
poetry-bumpversion
插件,您可以添加
[tool.poetry_bumpversion.file."widget/__init__.py"]

pyproject.toml

,然后

% poetry version patch
Bumping version from 0.7.9 to 0.7.10
poetry_bumpversion: processed file widget/__init__.py

% git diff -U0
diff --git a/widget/__init__.py b/widget/__init__.py
index 18c7cbf..9ff9982 100644
--- a/widget/__init__.py
+++ b/widget/__init__.py
@@ -1 +1 @@
-__version__ = "0.7.9"
+__version__ = "0.7.10"
diff --git a/pyproject.toml b/pyproject.toml
index 1b86c6e..5de1ce1 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -3 +3 @@ name = "widget"
-version = "0.7.9"
+version = "0.7.10"
@@ -55,0 +56,2 @@ tox = "^4.6.4"
+[tool.poetry_bumpversion.file."widget/__init__.py"]
+



0
投票
类似的讨论

中提供了同一问题的答案。这是一份副本:


project.toml

中,您可以通过不同的方式指定版本:


    诗歌
  • 期待[tool.poetry]中的版本:
    
    
  • [tool.poetry] name = "my-package" version = "0.1.0"
    Python 打包用户指南
  • 预计版本位于 [project] 部分:
    
    
  • [project] name = "my-package" version = "2020.0.0"
下一步是您可能想查看已安装软件包的版本(例如通过 
pip

poetry
)或您的应用程序。下一个:
import importlib.metadata

version = importlib.metadata.version("my-package")
print(version)

此代码适用于已安装的软件包。要使其与您的项目一起使用,您
应该使用

pip install -e .或类似的东西安装它。

如果您想在不安装的情况下检查项目的版本

,那么您可以使用以下代码片段:

from pathlib import Path import toml version = "unknown" # adopt path to your pyproject.toml pyproject_toml_file = Path(__file__).parent / "pyproject.toml" if pyproject_toml_file.exists() and pyproject_toml_file.is_file(): data = toml.load(pyproject_toml_file) # check project.version if "project" in data and "version" in data["project"]: version = data["project"]["version"] # check tool.poetry.version elif "tool" in data and "poetry" in data["tool"] and "version" in data["tool"]["poetry"]: version = data["tool"]["poetry"]["version"] print(version)

要使其正常工作,您应该提前安装
toml

软件包。

    

© www.soinside.com 2019 - 2024. All rights reserved.