如何在命令行 (Python) 获取 `setup.cfg` 元数据

发布于 2025-01-10 11:24:13 字数 432 浏览 0 评论 0 原文

当您有 setup.py 文件时,您可以通过以下命令获取包的名称:

C:\some\dir>python setup.py --name

这会将包的名称打印到命令行。

为了遵循最佳实践,我试图通过将所有内容放入 setup.cfg 中来迁移 setup.py,因为之前的所有内容都在 中setup.py 是静态内容。

但我们的构建管道取决于能否调用 python setup.py --name 。我希望以不需要创建 setup.py 文件的方式重写管道。

当您有 setup.cfg 但没有 setup.py 文件时,是否有办法获取包的名称?

When you have a setup.py file, you can get the name of the package via the command:

C:\some\dir>python setup.py --name

And this would print the name of the package to the command line.

In an attempt to adhere to best practice, I'm trying to migrate away from setup.py by putting everything in setup.cfg since everything that was previously in setup.py was static content.

But our build pipeline depends on being able to call python setup.py --name. I'm looking to rewrite the pipeline in such a way that I don't need to create a setup.py file.

Is there way to get the name of the package when you have a setup.cfg but not a setup.py file?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

无敌元气妹 2025-01-17 11:24:13

TL;DR,使用 setuptools 配置 API https ://setuptools.pypa.io/en/latest/setuptools.html#configuration-api

在您的情况下,此行将给出包的名称:

python -c 'from setuptools.config import read_configuration as c; print(c("setup.cfg")["metadata"]["name"])'

编辑:

In setuptools v61.0.0 (24 Mar 2022) setuptools.config.read_configuration 已弃用 。使用新的 API,该命令变为:

python -c 'from setuptools.config.setupcfg import read_configuration as c; print(c("setup.cfg")["metadata"]["name"])'

说明:

Setuptools 公开了一个 read_configuration() 函数,用于解析配置的元数据和选项部分。在内部,setuptools 使用 configparser 模块来解析配置文件 setup.cfg。对于简单的str类型数据,例如“name”键,可以使用configparser来读取数据。但是,setuptools 还允许使用指令进行动态配置直接用configparser解析。

下面的示例显示了替换 python setup.py --version 的两种方法之间的差异:

$ tree .
.
├── my_package
│   └── __init__.py
├── pyproject.toml
└── setup.cfg

1 directory, 3 files

$ cat setup.cfg
[metadata]
name = my_package
version = attr:my_package.__version__

[options]
packages = find:

$ cat my_package/__init__.py 
__version__ = "1.0.0"

$ cat pyproject.toml

$ python -c 'from setuptools.config import read_configuration as c; print(c("setup.cfg")["metadata"]["version"])'
1.0.0

$ python -c 'from configparser import ConfigParser; c = ConfigParser(); c.read("setup.cfg"); print(c["metadata"]["version"])'
attr:my_package.__version__

TL;DR, use the setuptools configuration API https://setuptools.pypa.io/en/latest/setuptools.html#configuration-api.

In your case, this line will give the name of the package:

python -c 'from setuptools.config import read_configuration as c; print(c("setup.cfg")["metadata"]["name"])'

Edit:

In setuptools v61.0.0 (24 Mar 2022) setuptools.config.read_configuration was deprecated . Using the new API, the command becomes:

python -c 'from setuptools.config.setupcfg import read_configuration as c; print(c("setup.cfg")["metadata"]["name"])'

Explanation:

Setuptools exposes a read_configuration() function for parsing metadata and options sections of the configuration. Internally, setuptools uses the configparser module to parse the configuration file setup.cfg. For simple str-type data such as the "name" key, configparser can be used to read the data. However, setuptools also allows dynamic configuration using directives that cannot be directly parsed with configparser.

Here is an example that shows the difference between the two approaches for replacing python setup.py --version:

$ tree .
.
├── my_package
│   └── __init__.py
├── pyproject.toml
└── setup.cfg

1 directory, 3 files

$ cat setup.cfg
[metadata]
name = my_package
version = attr:my_package.__version__

[options]
packages = find:

$ cat my_package/__init__.py 
__version__ = "1.0.0"

$ cat pyproject.toml

$ python -c 'from setuptools.config import read_configuration as c; print(c("setup.cfg")["metadata"]["version"])'
1.0.0

$ python -c 'from configparser import ConfigParser; c = ConfigParser(); c.read("setup.cfg"); print(c["metadata"]["version"])'
attr:my_package.__version__

So尛奶瓶 2025-01-17 11:24:13

也许使用 ConfigParser Python 模块?

python -c "from configparser import ConfigParser; cf = ConfigParser(); cf.read('setup.cfg'); print(cf['metadata']['name'])"

Maybe using the ConfigParser Python module ?

python -c "from configparser import ConfigParser; cf = ConfigParser(); cf.read('setup.cfg'); print(cf['metadata']['name'])"
病毒体 2025-01-17 11:24:13

对于允许从任何 < 获取任何元数据字段的“过度杀伤”解决方案em>PEP 517兼容项目(即pyproject.toml),在build 项目

#!/usr/bin/env python3

import argparse
import pathlib

import build.util

def _main():
    args_parser = argparse.ArgumentParser()
    args_parser.add_argument('path')
    args = args_parser.parse_args()
    path_name = getattr(args, 'path')
    path = pathlib.Path(path_name)
    #
    metadata = build.util.project_wheel_metadata(path)
    print(metadata)

if __name__ == '__main__':
    _main()

这实际上会调用构建后端(setuptoolspoetry >、flitpdm 或 waterever),因此这可能需要几秒钟的时间。

build.util API 已记录 “0.7.0 (16-09-2021)”,在此 改变


但是,是的,实际上,正如您已经说过的那样,我建议只保留最小的 setup.py:

#!/usr/bin/env python3

import setuptools
setuptools.setup()

以便 python setup.py --name 继续工作

当然正如其他人已经说过的,解析是一种可行且简单的解决方案。 setuptools 使用 ConfigParser 从标准库读取setup.cfg文件,所以你也可以这样做。


另一种可能的解决方案(归功于 wim):

python -c 'import setuptools; setuptools.setup()' --name

For an "over-kill" solution that allows getting any meta-data field from any PEP 517-compatible project (i.e. pyproject.toml), with the help of the build project:

#!/usr/bin/env python3

import argparse
import pathlib

import build.util

def _main():
    args_parser = argparse.ArgumentParser()
    args_parser.add_argument('path')
    args = args_parser.parse_args()
    path_name = getattr(args, 'path')
    path = pathlib.Path(path_name)
    #
    metadata = build.util.project_wheel_metadata(path)
    print(metadata)

if __name__ == '__main__':
    _main()

This will actually call the build back-end (setuptools, poetry, flit, pdm, or watever), so this might take some seconds.

The build.util API is documented here (on "latest") and it was added in "0.7.0 (16-09-2021)", in this change.


But yes, realistically, as you have already said it I would recommend just keeping a minimal setup.py:

#!/usr/bin/env python3

import setuptools
setuptools.setup()

so that python setup.py --name keeps working

And of course, as others have already said it, parsing is a viable and simple solution. setuptools uses ConfigParser from the standard library to read the setup.cfg file, so you can do it as well.


Another possible solution (credit to wim):

python -c 'import setuptools; setuptools.setup()' --name
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文