让sphinx使用setup.py中的版本

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

如果我这样做

sphinx-quickstart
我会被问到项目的版本。

我想避免有两个地方存放我的项目版本。

如何在Python打包世界中做到这一点?

python package python-sphinx
7个回答
32
投票

最简单(也可能是最干净)的方法是为顶级包的 __version__

 定义 
__init__.py
,然后导入该包并读取 
setup.py
和 Sphinx 项目的
conf.py
中的版本.

假设您的项目名为

myproject

将当前版本移出

setup.py
,并将其设为
myproject/__init__.py
中的变量:

myproject/__init__.py

# import foo
# ...

__version__ = '1.5'

在项目的

myproject
中导入
setup.py
,并将硬编码版本替换为
myproject.__version__

setup.py

from setuptools import setup
from myproject import __version__


project = "myproject"

setup(
    name=project,
    version=__version__,
    # ...
)

在您的 Sphinx 项目的

conf.py
中,执行相同的操作。因此,请按照以下方式编辑生成的
conf.py

docs/conf.py

from myproject import __version__

# ...

# The short X.Y version.
version = __version__
# The full version, including alpha/beta/rc tags.
release = version

有关执行此操作的库的示例与此几乎完全相同,请查看

requests
模块 (
__init__.py
|
setup.py
|
conf.py
)。

这将处理使用项目版本的自动生成的文本(例如文档首页的链接)。如果您想在特定的自定义位置使用您的版本,您可以使用

rst_epilog
指令动态插入
conf.py
中定义的配置值。


7
投票

也许更干净的选择是从

setup.py
命令实际构建 sphinx,如 http://www.sphinx-doc.org/en/master/setuptools.html:

中所述

设置.py

# this is only necessary when not using setuptools/distribute
from sphinx.setup_command import BuildDoc
cmdclass = {'build_sphinx': BuildDoc}

name = 'My project'
version = '1.2'
release = '1.2.0'
setup(
    name=name,
    author='Bernard Montgomery',
    version=release,
    cmdclass=cmdclass,
    # these are optional and override conf.py settings
    command_options={
        'build_sphinx': {
            'project': ('setup.py', name),
            'version': ('setup.py', version),
            'release': ('setup.py', release),
            'source_dir': ('setup.py', 'doc')}},
)

然后使用

构建文档
$ python setup.py build_sphinx

好处:

  • 使
    setup.py
    成为版本号的单一来源
  • 避免不必要地从项目文件夹中制作包

5
投票

从 pyproject.toml 中提取信息

如果您使用

pyproject.toml
,您也可以在
conf.py
中使用 tomli 解析它,或者在使用 python ^3.11 时使用等效的 tomllib
像这样,您可以从
pyproject.toml
中提取信息并在 sphinx 文档配置中使用它。

这里是一个使用

tomli
的简短不完整示例,假设
conf.py

位于
<project-root>/docs/source/conf.py
:

# conf.py

import tomli
with open("../../pyproject.toml", "rb") as f:
    toml = tomli.load(f)

# -- Project information -----------------------------------------------------

pyproject = toml["tool"]["poetry"]

project = pyproject["name"]
version = pyproject["version"]
release = pyproject["version"]

copyright = ...
author = ...

# and the rest of the configuration

4
投票

您可以查看

bumpversion
模块:

“一个小型命令行工具,通过正确的增量更新源代码中的所有版本字符串来简化软件发布”

您可以使用配置文件

.bumpversion.cfg
进行复杂的多文件操作。


4
投票

这是一个简单的解决方案,讽刺的是来自 setuptools_scm PyPI 页面

# contents of docs/conf.py
from importlib.metadata import version
release = version('myproject')
# for example take major/minor
version = '.'.join(release.split('.')[:2])

这是他们为什么不鼓励使用他们的 Sphinx 软件包的解释:

根本原因是,像阅读文档这样的服务有时会出于充分的原因更改工作目录,并且使用已安装的元数据可以防止在那里使用不必要的易失性数据。


3
投票

另一种方法是将

setuptools_scm
集成到您的项目中。这样你就可以

from setuptools_scm import get_version

version = get_version()

在你的

conf.py


0
投票

这是https://stackoverflow.com/users/2614160/jan's优秀的answerhatchling(而不是诗歌)变体,还有一些额外的东西。

获取版本

额外的一件事是它具有

my_package/__about__.py
中版本的真实来源, 所以我不会把它从
pyproject.toml
中拉出来。

我的狮身人面像

conf.py
包含类似的东西。

# conf.py
import os
import sys

# ...

sys.path.insert(0, os.path.abspath("."))
sys.path.insert(0, os.path.abspath("../../src"))

from my_package import __about__  # noqa: E402

version = __about__.__version__

请注意,

"../../src"
路径可能会有所不同,具体取决于您的项目布局。

来自孵化幼体的元数据
pyproject.toml

# conf.py

import tomllib

# ...

# Pull general sphinx project info from pyproject.toml
# Modified from https://stackoverflow.com/a/75396624/1304076
with open("../../pyproject.toml", "rb") as f:
    toml = tomllib.load(f)

pyproject = toml["project"]

project = pyproject["name"]
release = version
author = ",".join(
  [author["name"] for author in pyproject["authors"]]
)
copyright = f"2024 {author}"
© www.soinside.com 2019 - 2024. All rights reserved.