我有一个知识分歧,我很感谢帮助。以下前两节给出了一些序言;第三个包含问题。我很乐意回答我的原始问题和有关如何更好/更清洁等问题的建议。用一个3.x特性测试一个2.7友好的Python包
的设置
我已经开发了在起始于2.7的Python的所有版本以及基于HTTP的库(使用Requests)。最近有人要求该库支持通过aiohttp的异步HTTP请求,正如你毫无疑问知道的那样,这个库需要Python> = 3.4.2。
我只需要翻出请求并将其替换为aiohttp,但我的用户群中有一小部分用户需要在Python 2.x中工作。所以,我决定在适当的设置中使用这两个库。
设想一个Client
对象做所有HTTP交易:
import mylib
client = mylib.Client()
data = client.get()
client.update_setting(<setting_id>)
# etc.
考虑之后,我觉得我想要做这样的事情:
client = mylib.Client(asynchronous=True)
...在这一点Client
的方法现在将使用异步,aiottp驱动的变体。如果用户试图在Python < 3.4.2上以这种方式实例化Client
,则会记录一条警告,并且该库会回退到使用同步Client
。
出版
我已经配置了我的setup.py
来处理这个问题:Python版本> = 3.4.2将安装aiohttp(及其相关项),而版本3.4.2 <不会:
import sys
import setuptools
BASE_ASYNC_PYTHON_VER = int(hex(0x030402f0), 16)
PACKAGES = ['mylib']
REQUIRED = ['requests']
EXTRAS = {}
# Handles environments with old versions of setuptools:
if int(setuptools.__version__.split(".", 1)[0]) < 18:
if sys.hexversion < BASE_ASYNC_PYTHON_VER:
REQUIRED.append('aiodns')
REQUIRED.append('aiohttp')
REQUIRED.append('cchardet')
else:
EXTRAS[":python_version>='3.4.2'"] = ['aiodns', 'aiohttp', 'cchardet']
# Removing extraneous stuff for this example:
setuptools.setup(
name='mylib',
version='1.0.0'
description='Just for grims',
packages=PACKAGES,
install_requires=REQUIRED,
extras_require=EXTRAS,
这个效果非常好:Python 2安装避开了那些额外的库,Python 3安装包含了它们。
问题带有...
测试
我用pipenv来管理我的依赖,并同时开发的virtualenv。我Pipfile
看起来是这样的:
[[source]]
url = "https://pypi.python.org/simple"
verify_ssl = true
[dev-packages]
detox = "*"
pytest = "*"
requests-mock = "*"
tox = "*"
twine = "*"
[packages]
aiodns = "*"
aiohttp = "*"
cchardet = "*"
requests = "*"
注意,似乎没有成为一个方式说,“只有安装包版本的Python X.Y.Z。”
我也使用tox跨多个Python版本运行我的测试;我tox.ini
看起来是这样的:
[tox]
envlist = py27, py36
[testenv]
passenv=HOME
deps = pipenv
commands=
pipenv install --dev
pipenv run py.test tests
(其中tests
包含一组pytest - 友好测试)
不幸的是,这个电抗器:两个py27
和py36
,TOX尝试安装所有的软件包(DEV和“正规”)从我的Pipfile
;当py27
试图安装aiohttp时,显然会窒息。
所以,问题是:我该如何充分(和Python)测试这两个版本的Python与这个逻辑和结构?