我怎样才能轻松制作自己的自定义 setup.py 命令?
How can I easily make my own custom setup.py commands?
在 JavaScript 项目中,我可以在 package.json
中指定以下内容:
{
"name": "dredd",
"version": "1.0.4",
"description": "API Blueprint testing tool",
"main": "lib/dredd.js",
"bin": {
"dredd": "bin/dredd"
},
"scripts": {
"lint": "coffeelint ./src",
"pretest": "npm run lint",
"test": "find ./test/ -name '*-test.coffee' | xargs mocha --compilers 'coffee:coffee-script/register' --reporter spec --timeout 120000 --recursive",
...
"coveralls": "./scripts/coveralls.sh",
...
},
"dependencies": {
...
请参阅 scripts
部分。我可以定义任何 "script" 的任何名称和任何实现。然后我可以运行它作为npm run <name>
(有些特殊的我什至可以直接运行作为npm <name>
,例如npm test
)。 "script" 的实现可以只是一个命令或一行,其工作方式与我的 shell 中的工作方式相同(虽然可移植性是我需要自己实现的,npm
对我没有帮助,但没关系)。 npm 正确传播任何给定的参数以及退出代码。所以综上所述,我可以:
- 定义自定义命令
- 定义
pre<name>
命令,这些命令总是在 <name>
命令被调用之前执行
- 这些命令基本上可以是我终端运行中的任何命令
- 它们开箱即用地正确传播参数和退出代码
- 理想情况下,父命令可以列出可用的脚本
所以它类似于rake
、make
、grunt
、gulp
等,但是内置且非常简单,非常容易操作。我在 Python 项目中错过了这样的事情。我觉得 setup.py
是一个文件,最初是作为 单一入口点 到 Python 项目,我喜欢这个想法,我愿意接受它.理想情况下,我想要这样的东西:
python setup.py test
python setup.py lint
python setup.py <my command>
我想要单一入口点,因为我希望我的项目直观。人们不应该被迫阅读我的项目的文档或 .travis.yml
到 运行 linter、测试等。他们不需要关心我是使用 nosetests
还是 py.test
进行测试,还是使用 flake8
进行 linting。那是实现细节。
然而,这显然并不容易实现。例如。我希望我的 lint
命令在内部包含 flake8
以及其他内容。然后我希望我的 test
命令也总是 运行 lint
在 运行 本身之前。
我已经看到一些通过子classing Command
和在 setup.py
中的 setup(...)
中声明此类命令来实现自定义命令的方法,但是我找不到好的官方文档。此外,许多文章都是旧的,很难理解 2016 年的现状和当前的最佳实践,因为历史上有多个项目处理包装(distutils
、setuptools
、pip
, easy_install
, ...)。即使我能够实现 class 并调用它并在 python setup.py --help
上列出命令,我仍然必须自己实现子进程部分、退出代码、标准输入、标准错误和参数重定向.这对我的场景来说太复杂了,我想让我的项目保持简单并专注于它自己的目的。
测试框架通常采用实现一些重量级自定义命令的方式,这些命令可以设置为 python setup.py test
的替代品。实现有数百行,如果我想在命令中添加一些东西(例如,如果我想在每次调用 python setup.py test
时 flake8 && pytest tests
),那似乎很难实现。
我见过很多人放弃正确设计命令,因为它们太难写了,而且他们 just do following:
# setup.py
if sys.argv[0] == 'test':
# do something
if sys.argv[0] == 'publish':
# do something
setup(...
这很简单,但它没有集成到现有的 setup.py
基础架构中,如果我只想调用 shell 命令,我仍然需要自己实现所有子流程工作。另外我不确定是否可以轻松调用原始命令(例如,我想用一些东西包装 python setup.py test
,所以我会写下 if sys.argv[0] == 'test':
块并做一些自定义的事情,但我怎样才能继续之后进行测试?同样,找不到这方面的文档...)。
以上两个选项都不容易编写或维护。但是,我认为 Python 生态系统中没有我正在寻找的东西。我想我必须遗漏一些东西。有人能至少指出我正确的方向吗?至少向我解释 setuptools
和 distutils
的情况,我在哪里可以找到所有相关文档?
超级简单的准系统方法。不过需要在您的系统上安装 flake8
。
class Flake8(Command):
def initialize_options(self):
pass
def finalize_options(self):
pass
def run(self):
errno = os.system("flake8 <dir-needing-linting>")
sys.exit(errno)
在 JavaScript 项目中,我可以在 package.json
中指定以下内容:
{
"name": "dredd",
"version": "1.0.4",
"description": "API Blueprint testing tool",
"main": "lib/dredd.js",
"bin": {
"dredd": "bin/dredd"
},
"scripts": {
"lint": "coffeelint ./src",
"pretest": "npm run lint",
"test": "find ./test/ -name '*-test.coffee' | xargs mocha --compilers 'coffee:coffee-script/register' --reporter spec --timeout 120000 --recursive",
...
"coveralls": "./scripts/coveralls.sh",
...
},
"dependencies": {
...
请参阅 scripts
部分。我可以定义任何 "script" 的任何名称和任何实现。然后我可以运行它作为npm run <name>
(有些特殊的我什至可以直接运行作为npm <name>
,例如npm test
)。 "script" 的实现可以只是一个命令或一行,其工作方式与我的 shell 中的工作方式相同(虽然可移植性是我需要自己实现的,npm
对我没有帮助,但没关系)。 npm 正确传播任何给定的参数以及退出代码。所以综上所述,我可以:
- 定义自定义命令
- 定义
pre<name>
命令,这些命令总是在<name>
命令被调用之前执行 - 这些命令基本上可以是我终端运行中的任何命令
- 它们开箱即用地正确传播参数和退出代码
- 理想情况下,父命令可以列出可用的脚本
所以它类似于rake
、make
、grunt
、gulp
等,但是内置且非常简单,非常容易操作。我在 Python 项目中错过了这样的事情。我觉得 setup.py
是一个文件,最初是作为 单一入口点 到 Python 项目,我喜欢这个想法,我愿意接受它.理想情况下,我想要这样的东西:
python setup.py test
python setup.py lint
python setup.py <my command>
我想要单一入口点,因为我希望我的项目直观。人们不应该被迫阅读我的项目的文档或 .travis.yml
到 运行 linter、测试等。他们不需要关心我是使用 nosetests
还是 py.test
进行测试,还是使用 flake8
进行 linting。那是实现细节。
然而,这显然并不容易实现。例如。我希望我的 lint
命令在内部包含 flake8
以及其他内容。然后我希望我的 test
命令也总是 运行 lint
在 运行 本身之前。
我已经看到一些通过子classing Command
和在 setup.py
中的 setup(...)
中声明此类命令来实现自定义命令的方法,但是我找不到好的官方文档。此外,许多文章都是旧的,很难理解 2016 年的现状和当前的最佳实践,因为历史上有多个项目处理包装(distutils
、setuptools
、pip
, easy_install
, ...)。即使我能够实现 class 并调用它并在 python setup.py --help
上列出命令,我仍然必须自己实现子进程部分、退出代码、标准输入、标准错误和参数重定向.这对我的场景来说太复杂了,我想让我的项目保持简单并专注于它自己的目的。
测试框架通常采用实现一些重量级自定义命令的方式,这些命令可以设置为 python setup.py test
的替代品。实现有数百行,如果我想在命令中添加一些东西(例如,如果我想在每次调用 python setup.py test
时 flake8 && pytest tests
),那似乎很难实现。
我见过很多人放弃正确设计命令,因为它们太难写了,而且他们 just do following:
# setup.py
if sys.argv[0] == 'test':
# do something
if sys.argv[0] == 'publish':
# do something
setup(...
这很简单,但它没有集成到现有的 setup.py
基础架构中,如果我只想调用 shell 命令,我仍然需要自己实现所有子流程工作。另外我不确定是否可以轻松调用原始命令(例如,我想用一些东西包装 python setup.py test
,所以我会写下 if sys.argv[0] == 'test':
块并做一些自定义的事情,但我怎样才能继续之后进行测试?同样,找不到这方面的文档...)。
以上两个选项都不容易编写或维护。但是,我认为 Python 生态系统中没有我正在寻找的东西。我想我必须遗漏一些东西。有人能至少指出我正确的方向吗?至少向我解释 setuptools
和 distutils
的情况,我在哪里可以找到所有相关文档?
超级简单的准系统方法。不过需要在您的系统上安装 flake8
。
class Flake8(Command):
def initialize_options(self):
pass
def finalize_options(self):
pass
def run(self):
errno = os.system("flake8 <dir-needing-linting>")
sys.exit(errno)