为使用pyproject.toml和setuptools的Python项目实现自定义动态版本提供器的方法咨询
嘿,这个问题问得特别到位!我正好研究过类似的需求,来给你一步步捋清楚怎么实现,完全可以做到像setuptools_scm那样只在build-system里配置就行~
首先得搞懂setuptools是怎么识别这类工具的:它支持构建时依赖钩子机制,setuptools_scm就是靠这个实现自动版本获取的。当你把自定义模块加到build-system.requires里后,setuptools在构建过程中会自动触发模块里的特定逻辑来拉取元数据。
下面是具体的实现步骤:
第一步:编写自定义元数据提供模块
先创建一个比如叫my_custom_metadata.py的文件,把你自己的版本、作者、描述逻辑写进去,示例代码如下:def get_version(): # 这里替换成你的自定义逻辑,比如读VERSION文件、解析git标签、计算版本号等 return "1.2.3-my-custom" def get_author(): return "你的名字" def get_description(): return "我的超棒自定义项目"第二步:配置pyproject.toml
首先在[build-system]部分添加你的自定义模块(如果是本地模块,直接用./指代当前目录;如果是打包好的PyPI包,就写包名):[build-system] requires = ["setuptools", "wheel", "./"] build-backend = "setuptools.build_meta"然后在
[tool.setuptools.dynamic]里指定每个动态元数据对应的获取函数,告诉setuptools去哪里拿这些信息:[tool.setuptools.dynamic] version = {attr = "my_custom_metadata.get_version"} author = {attr = "my_custom_metadata.get_author"} description = {attr = "my_custom_metadata.get_description"}第三步:理解背后的工作机制
setuptools构建时会先解析pyproject.toml的build-system部分,安装所有依赖,然后启动构建后端。当处理动态元数据时,它会根据[tool.setuptools.dynamic]的配置,自动导入你指定的模块并调用对应的函数,把返回值作为项目的元数据。如果你想做成像
setuptools_scm那样的通用工具(不需要用户手动配置dynamic字段就能自动识别),还可以通过**入口点(entry point)**来实现。比如在你的模块自己的pyproject.toml里添加:[project.entry-points."setuptools_scm.parse_scm"] my_custom = "my_custom_metadata:parse_my_custom_scm"不过这属于进阶玩法,如果你只是给自己的项目用,前面的简单配置就足够了。
另外要注意:如果你的自定义逻辑需要访问项目文件(比如读VERSION文件),要确保路径处理正确,因为
setuptools构建时会用临时环境,但只要模块和项目文件在同一目录,一般都没问题。
备注:内容来源于stack exchange,提问作者avishorp

