在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
部分。我可以定义任何名称和任何实现的任何“脚本”。然后我可以将其作为npm run <name>
运行(还有一些我可以直接以npm <name>
运行的特殊项,例如npm test
)。 “脚本”的实现可以只是一个命令或一行,其工作方式与我在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,tests等。他们不应该关心我是使用nosetests
还是py.test
进行测试还是使用flake8
来进行测试。这是实施细节。
然而,这显然不容易实现。例如。我希望我的lint
命令在内部包含flake8
,也可能包含其他内容。然后我希望我的test
命令在运行之前始终运行lint
。
我已经看到了一些通过子类化Command
来实现自定义命令的方法,并在setup(...)
的{{1}}中声明了这样的命令,但我发现没有很好的官方文档。此外,许多文章都很陈旧,很难理解2016年的当前状态和当前最佳实践,因为历史上有多个涉及包装的项目(setup.py
,distutils
,setuptools
, pip
,......)。即使我能够实现该类并调用它并在easy_install
上列出命令,我仍然必须自己实现子进程部分,退出代码,stdin,stderr和参数重定向。这对我的场景来说太复杂了,我想让我的项目变得简单并专注于它自己的目的。
测试框架通常采用实现一些重量级自定义命令的方式,这些命令可以设置为python setup.py --help
的替代。实现是数百行,如果我想在命令中添加一些内容(例如,如果我每次调用python setup.py test
时都想flake8 && pytest tests
),那似乎很难实现。
我见过许多人因为难以编写并且just do following而无法正确设计命令而辞职:
python setup.py test
这很简单,但它没有集成到现有的# setup.py
if sys.argv[0] == 'test':
# do something
if sys.argv[0] == 'publish':
# do something
setup(...
基础架构中,如果我只想调用shell命令,我仍然需要自己实现所有子进程工作。另外我不确定是否可以轻松调用原始命令(例如,我想用setup.py
包装内容,所以我会写下python setup.py test
块并做一些自定义的事情,但我怎么能继续之后进行测试?再次找不到这方面的文档......)。
上述两种选项都不易编写或维护。但是,我不相信我在Python生态系统中正在寻找什么。我想我必须遗漏一些东西。有人能指出我至少朝着正确的方向前进吗?至少用if sys.argv[0] == 'test':
和setuptools
向我解释一下情况,在哪里可以找到所有相关文档?
答案 0 :(得分:1)
超级简单的准系统方法。需要在您的系统上安装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)