字幕:不仅是sdist
我正在尝试获取正在使用的程序包的setup.py
文件,以便与sdist
很好地配合使用。 setup.py
文件的相关部分是:
from setuptools.command.test import test
[...]
class Tox(test):
"as described in
http://tox.readthedocs.org/en/latest/example/basic.html?highlight=setuptools#integration-with-setuptools-distribute-test-commands"
[...]
def run_tests(self):
if self.distribution.install_requires:
self.distribution.fetch_build_eggs(
self.distribution.install_requires)
if self.distribution.tox_requires:
self.distribution.fetch_build_eggs(self.distribution.tox_requires)
# import here, cause outside the eggs aren't loaded
import tox
import shlex
args = self.tox_args
if args:
args = shlex.split(self.tox_args)
else:
args = ""
errno = tox.cmdline(args=args)
sys.exit(errno)
entry_points ={}
distutils_ext = {'distutils.setup_keywords': [
"tox_requires = setuptools.dist:check_requirements", ]
}
entry_points.update(distutils_ext)
setup(
install_requires=['six', 'numpy', 'matplotlib', 'scipy', 'astropy>=1',
'Pillow', ],
cmdclass={
'test': PyTest, # this is to run python setup.py test
'tox': Tox,
},
# list of packages and data
packages=find_packages(),
# tests
tests_require=['pytest', 'pytest-cov'],
tox_requires=['tox'],
# other keywords, mostly metadata
)
如果运行
python setup.py sdist
,则会在开始时收到警告:/usr/lib/python2.7/distutils/dist.py:267: UserWarning: Unknown distribution option: 'tox_requires'
warnings.warn(msg)
但是sdist可以正常工作,它会创建一个tar.gz文件,可以用来安装我的软件包。
但是,如果我第二次运行它,它将以(这是Pillow构建的开始)开始:
warning: no previously-included files found matching '.editorconfig'
Building using 4 processes
_imaging.c: In function ‘getink’:
并开始将所有必需的软件包构建到.eggs目录中。
如果删除* egg-info目录,则可以重新运行该命令。
如果我注释掉
tox_requires=[...]
行,则可以根据需要多次构建sdist。现在,根据setuptools documentation,上面的命令应该是运行向安装函数添加新参数的正确方法。
按照副标题,问题不仅出在
sdist
上,还可能是由于我对安装工具和需求的工作方式不甚了解。如果在没有安装tox的地方运行
python setup.py tox
,则在安装一些测试包后,不应安装(即pytest
和pytest-cov
):追溯(最近一次通话):
[...]
文件“ /usr/lib/python2.7/dist-packages/setuptools/command/test.py”,第127行,with_project_on_sys_path
func()
在run_tests中,文件“ setup.py”,第65行
如果self.distribution.tox_requires:
AttributeError:分发实例没有属性“ tox_requires”
[更新]
tox_requires
在安装过程中还会使点画非常混乱。如果已注释掉,我可以安装该软件包而不会出现任何问题;否则,它将开始编译包的源,并且系统地失败,因为在构建numpy
之类的文件时找不到scipy
如何获得setuptools以识别并正确使用
tox_requires
?解决此问题后,我认为我可以摆脱这里的虚假安装,在实现
Tox
类方面做得更好,也许可以覆盖test
的更多内容,也可以直接从Command
派生它 最佳答案
下述完整的(可行的)解决方案包括8个文件(包括简短文件)README.rst
),总共有43行代码。这比代码少
原始问题。
尽管很短,但它支持许多开发和测试方案
以非常方便的方式
无论如何,它不能完全回答您的问题,但是我敢肯定,它可以满足
背后的要求。
三行长setup.py
从技术上讲,可以将包含test
自动化功能的tox
命令放入您的setup.py
中,但是,结果可能非常混乱且难以理解。
可以用更简单的方式实现相同的结果:
对于开发人员,假设:
使用git
将tox
安装到系统中
对于包用户:
安装生成的软件包没有特殊要求
(可选)如果您希望用户通过单个命令测试软件包并将测试报告保存在中央服务器中:
安装devpi-server
并授予您的用户访问权限
要求您的用户安装$ pip install devpi
该解决方案基于以下工具和软件包:pbr
:简化包创建(包括)。通过git标签进行版本控制
从git commit消息创建AUTHORS
和ChangeLog
。pytest
:出色的测试框架,但任何其他框架都可以
代替它。tox
:出色的构建和测试自动化工具。coverage
:衡量测试覆盖率的工具(工作更简单pytest-cov
)
您也可以选择使用:devpi-server
:具有密码保护的私有PyPi服务器
访问。允许简单测试并提供测试报告收集。devpi
:类似于pip的工具。除了安装还支持
运行tox
定义的测试(安装,运行测试,逐步发布报告)。
创作包
创建新的项目目录并初始化git:
$ mkdir francesco
$ cd francesco
$ git init
创建一个包或模块
在这里,我们创建单个模块
francesco
,但同样适用于更多模块模块或软件包。
francesco.py
def main():
print("Hi, it is me, Francesco, keeping things simple.")
requirements.txt
创建用于实际安装软件包的软件包列表:
six
test_requirements.txt
定义测试所需的软件包:
pytest
coverage
tests/test_it.py
启动测试套件:
from francesco import main
def test_this():
main()
print("All seems fine to me")
assert True
setup.py
您是否梦想过愚蠢的简单
setup.py
?它去了:from setuptools import setup
setup(setup_requires=["pbr"], pbr=True)
setup.cfg
元数据属于配置文件:
[metadata]
name = francesco
author = Francesco Montesano
author-email = [email protected]
summary = Nice and simply installed python module supporting testing in different pythons
description-file = README.rst
[files]
modules=francesco
[entry_points]
console_scripts =
francesco = francesco:main
tox.ini
要配置tox自动构建和测试:
[tox]
envlist = py27, py34
[testenv]
commands =
coverage run --source francesco -m pytest -sv tests
coverage report
coverage html
deps =
-rtest_requirements.txt
README.rst
永远不要忘记
README.rst
:===========================================
Complex package with 3 line long `setup.py`
===========================================
Can we keep`setup.py` simple and still support automated testing?
...
tox
:在所有受支持的python版本中构建sdist并运行测试在项目目录的根目录中,只需运行单个命令
tox
:$ tox
GLOB sdist-make: /home/javl/sandbox/setuppy/setup.py
py27 inst-nodeps: /home/javl/sandbox/setuppy/.tox/dist/francesco-0.0.0.zip
py27 runtests: PYTHONHASHSEED='2409409075'
py27 runtests: commands[0] | coverage run --source francesco -m pytest -sv tests
============================= test session starts ==============================
platform linux2 -- Python 2.7.9, pytest-2.8.7, py-1.4.31, pluggy-0.3.1 -- /home/javl/sandbox/setuppy/.tox/py27/bin/python2.7
cachedir: .cache
rootdir: /home/javl/sandbox/setuppy, inifile:
collecting ... collected 1 items
tests/test_it.py::test_this Hi, it is me, Francesco, keeping things simple.
All seems fine to me
PASSED
=========================== 1 passed in 0.01 seconds ===========================
py27 runtests: commands[1] | coverage report
Name Stmts Miss Cover
----------------------------------
francesco.py 2 0 100%
py27 runtests: commands[2] | coverage html
py34 inst-nodeps: /home/javl/sandbox/setuppy/.tox/dist/francesco-0.0.0.zip
py34 runtests: PYTHONHASHSEED='2409409075'
py34 runtests: commands[0] | coverage run --source francesco -m pytest -sv tests
============================= test session starts ==============================
platform linux -- Python 3.4.2, pytest-2.8.7, py-1.4.31, pluggy-0.3.1 -- /home/javl/sandbox/setuppy/.tox/py34/bin/python3.4
cachedir: .cache
rootdir: /home/javl/sandbox/setuppy, inifile:
collecting ... collected 1 items
tests/test_it.py::test_this Hi, it is me, Francesco, keeping things simple.
All seems fine to me
PASSED
=========================== 1 passed in 0.01 seconds ===========================
py34 runtests: commands[1] | coverage report
Name Stmts Miss Cover
----------------------------------
francesco.py 2 0 100%
py34 runtests: commands[2] | coverage html
___________________________________ summary ____________________________________
py27: commands succeeded
py34: commands succeeded
congratulations :)
得到sdist
ls .tox/dist
francesco-0.0.0.zip
使用python 2.7 virtualenv开发
激活Python 2.7 virtualenv
$ source .tox/py27/bin/activate
运行测试
(py27) $ py.test -sv tests
==============================================================================================
test session starts
===============================================================================================
platform linux2 -- Python 2.7.9, pytest-2.8.7, py-1.4.31, pluggy-0.3.1
-- /home/javl/sandbox/setuppy/.tox/py27/bin/python2.7 cachedir: .cache
rootdir: /home/javl/sandbox/setuppy, inifile: collected 1 items
tests/test_it.py::test_this Hi, it is me, Francesco, keeping things
simple. All seems fine to me PASSED
============================================================================================
1 passed in 0.01 seconds
============================================================================================
测量测试范围
(py27)$ coverage run --source francesco -m pytest -sv tests
.....
(py27)$ coverage report
Name Stmts Miss Cover
----------------------------------
francesco.py 2 0 100%
在网络浏览器中查看覆盖率报告
(py27)$ coverage html
(py27)$ firefox htmlcov/index.html
发布新的软件包版本
(可选)安装本地
devpi-server
这里没有介绍devpi-server的安装,但是非常
简单,尤其是如果您仅将其安装到本地计算机上
个人测试。
提交源代码,分配版本标签
确保所有源代码都已提交。
评估版本标签:
$ git tag -a 0.1
通过tox重新运行测试并构建sdist
确保您已停用virtualenv(否则与
毒):
(py27)$ deactivate
运行
tox
:$ tox
.....
...it builds as usual, may fail, if you have forgotten to commit some changes or files...
查找软件包新版本的sdist:
$ ls .tox/dist/francesco-0.1.0.
.tox/dist/francesco-0.1.0.zip
大功告成您可以分发软件包的新测试版本
通常向用户显示。
(可选)将sdist上传到devpi-server并在本地进行测试
假设执行以下步骤,您已安装并运行
devpi-server
。$ devpi login javl
...enter your password...
$ devpi upload .tox/dist/francesco-0.1.0.zip
在干净的环境中测试包装
(如果激活,请禁用virtualenv):
$ cd /tmp
$ mkdir testing
$ cd testing
$ devpi test francesco
received http://localhost:3141/javl/dev/+f/4f7/c13fee84bb7c8/francesco-0.1.0.zip
unpacking /tmp/devpi-test6/downloads/francesco-0.1.0.zip to /tmp/devpi-test6/zip
/tmp/devpi-test6/zip/francesco-0.1.0$ tox --installpkg /tmp/devpi-test6/downloads/francesco-0.1.0.zip -i ALL=http://localhost:3141/javl/dev/+simple/ --recreate --result-json /tmp/devpi-test6/zip/toxreport.json
-c /tmp/devpi-test6/zip/francesco-0.1.0/tox.ini
py27 create: /tmp/devpi-test6/zip/francesco-0.1.0/.tox/py27
py27 installdeps: -rtest_requirements.txt
py27 inst: /tmp/devpi-test6/downloads/francesco-0.1.0.zip
py27 installed: coverage==4.0.3,francesco==0.1.0,py==1.4.31,pytest==2.8.7,six==1.10.0,wheel==0.24.0
py27 runtests: PYTHONHASHSEED='3916044270'
py27 runtests: commands[0] | coverage run --source francesco -m pytest -sv tests
============================= test session starts ==============================
platform linux2 -- Python 2.7.9, pytest-2.8.7, py-1.4.31, pluggy-0.3.1 -- /tmp/devpi-test6/zip/francesco-0.1.0/.tox/py27/bin/python2.7
cachedir: .cache
rootdir: /tmp/devpi-test6/zip/francesco-0.1.0, inifile:
collecting ... collected 1 items
tests/test_it.py::test_this Hi, it is me, Francesco, keeping things simple.
All seems fine to me
PASSED
=========================== 1 passed in 0.01 seconds ===========================
py27 runtests: commands[1] | coverage report
Name Stmts Miss Cover
----------------------------------
francesco.py 2 0 100%
py27 runtests: commands[2] | coverage html
py34 create: /tmp/devpi-test6/zip/francesco-0.1.0/.tox/py34
py34 installdeps: -rtest_requirements.txt
py34 inst: /tmp/devpi-test6/downloads/francesco-0.1.0.zip
py34 installed: coverage==4.0.3,francesco==0.1.0,py==1.4.31,pytest==2.8.7,six==1.10.0,wheel==0.24.0
py34 runtests: PYTHONHASHSEED='3916044270'
py34 runtests: commands[0] | coverage run --source francesco -m pytest -sv tests
============================= test session starts ==============================
platform linux -- Python 3.4.2, pytest-2.8.7, py-1.4.31, pluggy-0.3.1 -- /tmp/devpi-test6/zip/francesco-0.1.0/.tox/py34/bin/python3.4
cachedir: .cache
rootdir: /tmp/devpi-test6/zip/francesco-0.1.0, inifile:
collecting ... collected 1 items
tests/test_it.py::test_this Hi, it is me, Francesco, keeping things simple.
All seems fine to me
PASSED
=========================== 1 passed in 0.01 seconds ===========================
py34 runtests: commands[1] | coverage report
Name Stmts Miss Cover
----------------------------------
francesco.py 2 0 100%
py34 runtests: commands[2] | coverage html
____________________________________________________________________________________________________ summary _____________________________________________________________________________________________________
py27: commands succeeded
py34: commands succeeded
congratulations :)
wrote json report at: /tmp/devpi-test6/zip/toxreport.json
posting tox result data to http://localhost:3141/javl/dev/+f/4f7/c13fee84bb7c8/francesco-0.1.0.zip
successfully posted tox result data
您可以在网络浏览器中检查测试结果:
$ firefox http://localhost:3141
然后搜索“ francesco”软件包,单击软件包名称,在表中查找
列,名称为“毒性结果”,单击此处以显示环境设置和测试
结果。
让您的用户测试软件包
假设您的
devpi-server
正在运行,并且您的用户可以访问它。用户应安装
devpi
命令:$ pip install devpi
(请注意,此工具未安装
devpi-server
中的任何内容)帮助您的用户获得对
devpi-server
的访问权限(此处不介绍)。然后,用户只需运行测试:
$ devpi test francesco
运行测试后(它会自动使用
tox
,但用户没有关心一下),您可以在devpi网站的同一位置找到测试结果
界面,就像以前一样。
关于python - python setup.py sdist和自定义设置关键字不能一起使用,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/35059585/