Now use toxgen to produce the tox.ini file
This commit is contained in:
parent
f69c81b264
commit
3ecb245858
179
tox-tmpl.ini
Normal file
179
tox-tmpl.ini
Normal file
@ -0,0 +1,179 @@
|
||||
# content of: tox.ini , put in same dir as setup.py
|
||||
[tox]
|
||||
envlist = py27,py27-nolxml,py32,py32-nolxml,pypy,py25-simplejson,sphinxext,tg11,tg15,pecan,coverage
|
||||
|
||||
[common]
|
||||
testtools=
|
||||
nose
|
||||
coverage
|
||||
|
||||
[axes]
|
||||
python=py25,py27,py32,pypy
|
||||
sqlalchemy=sa5,sa6,sa7*
|
||||
lxml=lxml*,nolxml
|
||||
json=json*,simplejson
|
||||
|
||||
[axis:python]
|
||||
deps =
|
||||
{[common]testtools}
|
||||
transaction
|
||||
suds
|
||||
|
||||
commands=
|
||||
{envbindir}/coverage run {envbindir}/nosetests --with-xunit --xunit-file nosetests-{envname}.xml wsme/tests wsmeext/tests --verbose {posargs}
|
||||
{envbindir}/coverage xml -o coverage-{envname}.xml wsme/*.py wsme/rest/*.py wsmeext/*.py
|
||||
{envbindir}/coverage report --show-missing wsme/*.py wsme/rest/*.py wsmeext/*.py
|
||||
|
||||
[axis:python:py25]
|
||||
deps=
|
||||
{[common]testtools}
|
||||
zope.interface<=3.8.99
|
||||
transaction<=1.1.1
|
||||
suds
|
||||
basepython=python2.5
|
||||
|
||||
[axis:python:py27]
|
||||
basepython=python2.7
|
||||
|
||||
[axis:python:py32]
|
||||
basepython=python3.2
|
||||
|
||||
deps =
|
||||
{[common]testtools}
|
||||
transaction
|
||||
https://bitbucket.org/bernh/suds-python-3-patches/downloads/suds_patched.zip
|
||||
|
||||
commands=
|
||||
{envbindir}/coverage run {envbindir}/nosetests --with-xunit --xunit-file nosetests-{envname}.xml wsme/tests wsmeext/tests --verbose {posargs}
|
||||
{envbindir}/coverage xml -o coverage-{envname}.xml --omit wsmeext/sphinxext.py wsme/*.py wsme/rest/*.py wsmeext/*.py
|
||||
{envbindir}/coverage report --show-missing --omit wsmeext/sphinxext.py wsme/*.py wsme/rest/*.py wsmeext/*.py
|
||||
|
||||
[axis:sqlalchemy:sa5]
|
||||
deps=
|
||||
SQLAlchemy<=0.5.99
|
||||
|
||||
[axis:sqlalchemy:sa6]
|
||||
deps=
|
||||
SQLAlchemy<=0.6.99
|
||||
|
||||
[axis:sqlalchemy:sa7]
|
||||
deps=
|
||||
SQLAlchemy<=0.7.99
|
||||
|
||||
[axis:json:simplejson]
|
||||
deps=
|
||||
simplejson
|
||||
|
||||
constraints=
|
||||
!python:py32
|
||||
|
||||
[axis:lxml:lxml]
|
||||
deps=
|
||||
lxml
|
||||
|
||||
[axis:lxml:nolxml]
|
||||
constraints=
|
||||
!python:py25
|
||||
|
||||
[testenv]
|
||||
setenv=
|
||||
COVERAGE_FILE=.coverage.{envname}
|
||||
|
||||
downloadcache=.tox/cache
|
||||
|
||||
[testenv:sphinxext]
|
||||
basepython=python2.5
|
||||
deps=
|
||||
d2to1
|
||||
nose
|
||||
coverage
|
||||
simplejson
|
||||
Sphinx
|
||||
commands=
|
||||
{envbindir}/coverage run {envbindir}/nosetests --with-xunit --xunit-file nosetests-{envname}.xml tests/test_sphinxext.py --verbose {posargs}
|
||||
{envbindir}/coverage xml -o coverage-{envname}.xml wsme/*.py wsme/rest/*.py wsmeext/*.py
|
||||
{envbindir}/coverage report --show-missing wsme/*.py wsme/rest/*.py wsmeext/*.py
|
||||
|
||||
[testenv:tg11]
|
||||
basepython=python2.5
|
||||
deps=
|
||||
d2to1
|
||||
nose
|
||||
webtest
|
||||
coverage
|
||||
simplejson
|
||||
suds
|
||||
lxml
|
||||
commands=
|
||||
{envbindir}/easy_install -i http://www.turbogears.org/1.1/downloads/current/index/ 'TurboGears<1.1.99'
|
||||
{envbindir}/nosetests --with-xunit --xunit-file nosetests-{envname}.xml tests/test_tg1.py --verbose --with-coverage --cover-package wsme,wsmeext {posargs}
|
||||
{envbindir}/coverage xml -o coverage-{envname}.xml wsme/*.py wsme/rest/*.py wsmeext/*.py
|
||||
|
||||
[testenv:tg15]
|
||||
basepython=python2.5
|
||||
deps=
|
||||
d2to1
|
||||
nose
|
||||
webtest
|
||||
coverage
|
||||
simplejson
|
||||
suds
|
||||
lxml
|
||||
commands=
|
||||
{envbindir}/easy_install -i http://www.turbogears.org/1.5/downloads/current/index/ 'TurboGears<1.5.99'
|
||||
{envbindir}/nosetests --with-xunit --xunit-file nosetests-{envname}.xml tests/test_tg15.py --verbose --with-coverage --cover-package wsme,wsmeext {posargs}
|
||||
{envbindir}/coverage xml -o coverage-{envname}.xml wsme/*.py wsme/rest/*.py wsmeext/*.py
|
||||
|
||||
[testenv:tg21]
|
||||
basepython=python2.5
|
||||
deps=
|
||||
d2to1
|
||||
nose
|
||||
coverage
|
||||
simplejson
|
||||
commands=
|
||||
{envbindir}/easy_install -i http://www.turbogears.org/2.1/downloads/current/index/ 'TurboGears2<2.1.99' webtest
|
||||
{envbindir}/coverage run {envbindir}/nosetests --with-xunit --xunit-file nosetests-{envname}.xml tests/test_tg20.py --verbose {posargs}
|
||||
{envbindir}/coverage xml -o coverage-{envname}.xml wsme/*.py wsme/rest/*.py wsmeext/*.py
|
||||
{envbindir}/coverage report --show-missing wsme/*.py wsme/rest/*.py wsmeext/*.py
|
||||
|
||||
[testenv:pecan]
|
||||
basepython=python2.7
|
||||
deps=
|
||||
d2to1
|
||||
nose
|
||||
webtest
|
||||
coverage
|
||||
simplejson
|
||||
pecan
|
||||
setenv=
|
||||
PYTHONPATH={toxinidir}
|
||||
COVERAGE_FILE=.coverage.{envname}
|
||||
|
||||
commands=
|
||||
{envbindir}/nosetests -w tests/pecantest test/tests/test_ws.py --with-xunit --xunit-file nosetests-{envname}.xml --verbose --with-coverage --cover-package wsme,wsmeext {posargs}
|
||||
{envbindir}/coverage xml -o coverage-{envname}.xml wsme/*.py wsme/rest/*.py wsmeext/*.py
|
||||
|
||||
[testenv:coverage]
|
||||
basepython=python
|
||||
deps=
|
||||
coverage
|
||||
setenv=
|
||||
COVERAGE_FILE=.coverage
|
||||
commands=
|
||||
{envbindir}/coverage erase
|
||||
{envbindir}/coverage combine
|
||||
{envbindir}/coverage xml wsme/*.py wsme/rest/*.py wsmeext/*.py
|
||||
{envbindir}/coverage report --show-missing wsme/*.py wsme/protocols/*.py wsmeext/*.py
|
||||
|
||||
[testenv:doc]
|
||||
deps=
|
||||
Sphinx
|
||||
|
||||
changedir=
|
||||
doc
|
||||
|
||||
commands=
|
||||
{envbindir}/easy_install https://bitbucket.org/cdevienne/wsme-sqlalchemy/get/tip.zip
|
||||
{envbindir}/easy_install https://bitbucket.org/cdevienne/wsme-extdirect/get/tip.zip
|
||||
make clean ziphtml
|
144
toxgen.py
Normal file
144
toxgen.py
Normal file
@ -0,0 +1,144 @@
|
||||
"""
|
||||
Produce a tox.ini file from a template config file.
|
||||
|
||||
The template config file is a standard tox.ini file with additional sections.
|
||||
Theses sections will be combined to create new testenv: sections if they do
|
||||
not exists yet.
|
||||
|
||||
See REAME.rst for more detail.
|
||||
"""
|
||||
|
||||
import itertools
|
||||
import collections
|
||||
import optparse
|
||||
|
||||
try:
|
||||
from configparser import ConfigParser
|
||||
except:
|
||||
from ConfigParser import ConfigParser # noqa
|
||||
|
||||
|
||||
parser = optparse.OptionParser(epilog=__doc__)
|
||||
parser.add_option('-i', '--input', dest='input',
|
||||
default='tox-tmpl.ini', metavar='FILE')
|
||||
parser.add_option('-o', '--output', dest='output',
|
||||
default='tox.ini', metavar='FILE')
|
||||
|
||||
|
||||
class AxisItem(object):
|
||||
def __init__(self, axis, name, config):
|
||||
self.axis = axis
|
||||
self.isdefault = name[-1] == '*'
|
||||
self.name = name[:-1] if self.isdefault else name
|
||||
self.load(config)
|
||||
|
||||
def load(self, config):
|
||||
sectionname = 'axis:%s:%s' % (self.axis.name, self.name)
|
||||
if config.has_section(sectionname):
|
||||
self.options = collections.OrderedDict(config.items(sectionname))
|
||||
else:
|
||||
self.options = collections.OrderedDict()
|
||||
|
||||
for name, value in self.axis.defaults.items():
|
||||
if name not in self.options:
|
||||
self.options[name] = value
|
||||
|
||||
|
||||
class Axis(object):
|
||||
def __init__(self, name, config):
|
||||
self.name = name
|
||||
self.load(config)
|
||||
|
||||
def load(self, config):
|
||||
self.items = collections.OrderedDict()
|
||||
values = config.get('axes', self.name).split(',')
|
||||
if config.has_section('axis:%s' % self.name):
|
||||
self.defaults = collections.OrderedDict(
|
||||
config.items('axis:%s' % self.name)
|
||||
)
|
||||
else:
|
||||
self.defaults = {}
|
||||
for value in values:
|
||||
self.items[value.strip('*')] = AxisItem(self, value, config)
|
||||
|
||||
|
||||
def render(incfg):
|
||||
axes = collections.OrderedDict()
|
||||
|
||||
if incfg.has_section('axes'):
|
||||
for axis in incfg.options('axes'):
|
||||
axes[axis] = Axis(axis, incfg)
|
||||
|
||||
out = ConfigParser()
|
||||
for section in incfg.sections():
|
||||
if section == 'axes' or section.startswith('axis:'):
|
||||
continue
|
||||
out.add_section(section)
|
||||
for name, value in incfg.items(section):
|
||||
out.set(section, name, value)
|
||||
|
||||
for combination in itertools.product(
|
||||
*[axis.items.keys() for axis in axes.values()]):
|
||||
options = collections.OrderedDict()
|
||||
|
||||
section_name = (
|
||||
'testenv:' + '-'.join([item for item in combination if item])
|
||||
)
|
||||
section_alt_name = (
|
||||
'testenv:' + '-'.join([
|
||||
itemname
|
||||
for axis, itemname in zip(axes.values(), combination)
|
||||
if itemname and not axis.items[itemname].isdefault
|
||||
])
|
||||
)
|
||||
if section_alt_name == section_name:
|
||||
section_alt_name = None
|
||||
|
||||
axes_items = [
|
||||
'%s:%s' % (axis, itemname)
|
||||
for axis, itemname in zip(axes, combination)
|
||||
]
|
||||
|
||||
for axis, itemname in zip(axes.values(), combination):
|
||||
axis_options = axis.items[itemname].options
|
||||
if 'constraints' in axis_options:
|
||||
constraints = axis_options['constraints'].split('\n')
|
||||
for c in constraints:
|
||||
if c.startswith('!') and c[1:] in axes_items:
|
||||
continue
|
||||
for name, value in axis_options.items():
|
||||
if name in options:
|
||||
options[name] += value
|
||||
else:
|
||||
options[name] = value
|
||||
|
||||
constraints = options.pop('constraints', '').split('\n')
|
||||
neg_constraints = [c[1:] for c in constraints if c and c[0] == '!']
|
||||
if not set(neg_constraints).isdisjoint(axes_items):
|
||||
continue
|
||||
|
||||
if not out.has_section(section_name):
|
||||
out.add_section(section_name)
|
||||
|
||||
if (section_alt_name and not out.has_section(section_alt_name)):
|
||||
out.add_section(section_alt_name)
|
||||
|
||||
for name, value in reversed(options.items()):
|
||||
if not out.has_option(section_name, name):
|
||||
out.set(section_name, name, value)
|
||||
if section_alt_name and not out.has_option(section_alt_name, name):
|
||||
out.set(section_alt_name, name, value)
|
||||
|
||||
return out
|
||||
|
||||
|
||||
def main():
|
||||
options, args = parser.parse_args()
|
||||
tmpl = ConfigParser()
|
||||
tmpl.read(options.input)
|
||||
with open(options.output, 'wb') as outfile:
|
||||
render(tmpl).write(outfile)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
Loading…
Reference in New Issue
Block a user