diff options
| author | holger krekel <holger@merlinux.eu> | 2012-11-23 22:32:30 +0100 |
|---|---|---|
| committer | holger krekel <holger@merlinux.eu> | 2012-11-23 22:32:30 +0100 |
| commit | c23f32b2905239827b12d65f11ac4a745c413b0f (patch) | |
| tree | 78638e43e202793b33c12def90e1297dc3ab4326 | |
| parent | cdd8f99a7b52be286de34925f4cd31990f2994fe (diff) | |
| parent | e54f50beb67fdf787556d5a3a5905e6ed1686704 (diff) | |
| download | tox-c23f32b2905239827b12d65f11ac4a745c413b0f.tar.gz | |
merge
| -rw-r--r-- | doc/index.txt | 3 | ||||
| -rw-r--r-- | setup.py | 2 | ||||
| -rw-r--r-- | tests/test_quickstart.py | 326 | ||||
| -rw-r--r-- | tox/_quickstart.py | 255 |
4 files changed, 585 insertions, 1 deletions
diff --git a/doc/index.txt b/doc/index.txt index 2a4203c..e3e13eb 100644 --- a/doc/index.txt +++ b/doc/index.txt @@ -36,6 +36,9 @@ right next to your ``setup.py`` file:: deps=pytest # install pytest in the venvs commands=py.test # or 'nosetests' or ... +You can also try generating a ``tox.ini`` file automatically, by running +``tox-quickstart`` and then answering a few simple questions. + To sdist-package, install and test your project against Python2.6 and Python2.7, just type:: tox @@ -55,7 +55,7 @@ def main(): author='holger krekel', author_email='holger@merlinux.eu', packages=['tox', ], - entry_points={'console_scripts': 'tox=tox:cmdline'}, + entry_points={'console_scripts': 'tox=tox:cmdline\ntox-quickstart=tox._quickstart:main'}, # we use a public tox version to test, see tox.ini's testenv # "deps" definition for the required dependencies tests_require=['tox'], diff --git a/tests/test_quickstart.py b/tests/test_quickstart.py new file mode 100644 index 0000000..446954e --- /dev/null +++ b/tests/test_quickstart.py @@ -0,0 +1,326 @@ +import tox._quickstart + + +class TestToxQuickstartMain(object): + def mock_term_input_return_values(self, return_values): + for return_val in return_values: + yield return_val + + def get_mock_term_input(self, return_values): + generator = self.mock_term_input_return_values(return_values) + + def mock_term_input(prompt): + try: + return next(generator) + except NameError: + return generator.next() + + return mock_term_input + + def test_quickstart_main_choose_individual_pythons_and_pytest(self, monkeypatch, tmpdir): + monkeypatch.setattr( + tox._quickstart, 'term_input', + self.get_mock_term_input(['4', 'Y', 'Y', 'Y', 'Y', 'N', 'N', 'Y', 'Y', 'Y', 'N', 'py.test', 'pytest'])) + + tox._quickstart.main(argv=['tox-quickstart']) + + expected_tox_ini = """ +# Tox (http://tox.testrun.org/) is a tool for running tests +# in multiple virtualenvs. This configuration file will run the +# test suite on all supported python versions. To use it, "pip install tox" +# and then run "tox" from this directory. + +[tox] +envlist = py24, py25, py26, py27, py32, py33, pypy + +[testenv] +commands = py.test +deps = + pytest +""".lstrip() + result = open('tox.ini').read() + assert(result == expected_tox_ini) + + def test_quickstart_main_choose_individual_pythons_and_nose_adds_deps(self, monkeypatch, tmpdir): + monkeypatch.setattr( + tox._quickstart, 'term_input', + self.get_mock_term_input(['4', 'Y', 'Y', 'Y', 'Y', 'N', 'N', 'Y', 'Y', 'Y', 'N', 'nosetests', ''])) + + tox._quickstart.main(argv=['tox-quickstart']) + + expected_tox_ini = """ +# Tox (http://tox.testrun.org/) is a tool for running tests +# in multiple virtualenvs. This configuration file will run the +# test suite on all supported python versions. To use it, "pip install tox" +# and then run "tox" from this directory. + +[tox] +envlist = py24, py25, py26, py27, py32, py33, pypy + +[testenv] +commands = nosetests +deps = + nose +""".lstrip() + result = open('tox.ini').read() + assert(result == expected_tox_ini) + + def test_quickstart_main_choose_individual_pythons_and_trial_adds_deps(self, monkeypatch, tmpdir): + monkeypatch.setattr( + tox._quickstart, 'term_input', + self.get_mock_term_input(['4', 'Y', 'Y', 'Y', 'Y', 'N', 'N', 'Y', 'Y', 'Y', 'N', 'trial', ''])) + + tox._quickstart.main(argv=['tox-quickstart']) + + expected_tox_ini = """ +# Tox (http://tox.testrun.org/) is a tool for running tests +# in multiple virtualenvs. This configuration file will run the +# test suite on all supported python versions. To use it, "pip install tox" +# and then run "tox" from this directory. + +[tox] +envlist = py24, py25, py26, py27, py32, py33, pypy + +[testenv] +commands = trial +deps = + twisted +""".lstrip() + result = open('tox.ini').read() + assert(result == expected_tox_ini) + + def test_quickstart_main_choose_individual_pythons_and_pytest_adds_deps(self, monkeypatch, tmpdir): + monkeypatch.setattr( + tox._quickstart, 'term_input', + self.get_mock_term_input(['4', 'Y', 'Y', 'Y', 'Y', 'N', 'N', 'Y', 'Y', 'Y', 'N', 'py.test', ''])) + + tox._quickstart.main(argv=['tox-quickstart']) + + expected_tox_ini = """ +# Tox (http://tox.testrun.org/) is a tool for running tests +# in multiple virtualenvs. This configuration file will run the +# test suite on all supported python versions. To use it, "pip install tox" +# and then run "tox" from this directory. + +[tox] +envlist = py24, py25, py26, py27, py32, py33, pypy + +[testenv] +commands = py.test +deps = + pytest +""".lstrip() + result = open('tox.ini').read() + assert(result == expected_tox_ini) + + def test_quickstart_main_choose_py27_and_pytest_adds_deps(self, monkeypatch, tmpdir): + monkeypatch.setattr( + tox._quickstart, 'term_input', + self.get_mock_term_input(['1', 'py.test', ''])) + + tox._quickstart.main(argv=['tox-quickstart']) + + expected_tox_ini = """ +# Tox (http://tox.testrun.org/) is a tool for running tests +# in multiple virtualenvs. This configuration file will run the +# test suite on all supported python versions. To use it, "pip install tox" +# and then run "tox" from this directory. + +[tox] +envlist = py27 + +[testenv] +commands = py.test +deps = + pytest +""".lstrip() + result = open('tox.ini').read() + assert(result == expected_tox_ini) + + def test_quickstart_main_choose_py27_and_py33_and_pytest_adds_deps(self, monkeypatch, tmpdir): + monkeypatch.setattr( + tox._quickstart, 'term_input', + self.get_mock_term_input(['2', 'py.test', ''])) + + tox._quickstart.main(argv=['tox-quickstart']) + + expected_tox_ini = """ +# Tox (http://tox.testrun.org/) is a tool for running tests +# in multiple virtualenvs. This configuration file will run the +# test suite on all supported python versions. To use it, "pip install tox" +# and then run "tox" from this directory. + +[tox] +envlist = py27, py33 + +[testenv] +commands = py.test +deps = + pytest +""".lstrip() + result = open('tox.ini').read() + assert(result == expected_tox_ini) + + def test_quickstart_main_choose_all_pythons_and_pytest_adds_deps(self, monkeypatch, tmpdir): + monkeypatch.setattr( + tox._quickstart, 'term_input', + self.get_mock_term_input(['3', 'py.test', ''])) + + tox._quickstart.main(argv=['tox-quickstart']) + + expected_tox_ini = """ +# Tox (http://tox.testrun.org/) is a tool for running tests +# in multiple virtualenvs. This configuration file will run the +# test suite on all supported python versions. To use it, "pip install tox" +# and then run "tox" from this directory. + +[tox] +envlist = py24, py25, py26, py27, py30, py31, py32, py33, pypy, jython + +[testenv] +commands = py.test +deps = + pytest +""".lstrip() + result = open('tox.ini').read() + assert(result == expected_tox_ini) + + def test_quickstart_main_choose_individual_pythons_and_defaults(self, monkeypatch, tmpdir): + monkeypatch.setattr( + tox._quickstart, 'term_input', + self.get_mock_term_input(['4', '', '', '', '', '', '', '', '', '', '', '', ''])) + + tox._quickstart.main(argv=['tox-quickstart']) + + expected_tox_ini = """ +# Tox (http://tox.testrun.org/) is a tool for running tests +# in multiple virtualenvs. This configuration file will run the +# test suite on all supported python versions. To use it, "pip install tox" +# and then run "tox" from this directory. + +[tox] +envlist = py24, py25, py26, py27, py30, py31, py32, py33, pypy, jython + +[testenv] +commands = {envpython} setup.py test +deps = + +""".lstrip() + result = open('tox.ini').read() + assert(result == expected_tox_ini) + + +class TestToxQuickstart(object): + def test_pytest(self, tmpdir): + d = { + 'py24': True, + 'py25': True, + 'py26': True, + 'py27': True, + 'py32': True, + 'py33': True, + 'pypy': True, + 'commands': 'py.test', + 'deps': 'pytest', + } + expected_tox_ini = """ +# Tox (http://tox.testrun.org/) is a tool for running tests +# in multiple virtualenvs. This configuration file will run the +# test suite on all supported python versions. To use it, "pip install tox" +# and then run "tox" from this directory. + +[tox] +envlist = py24, py25, py26, py27, py32, py33, pypy + +[testenv] +commands = py.test +deps = + pytest +""".lstrip() + d = tox._quickstart.process_input(d) + tox._quickstart.generate(d) + result = open('tox.ini').read() + # print(result) + assert(result == expected_tox_ini) + + def test_setup_py_test(self, tmpdir): + d = { + 'py26': True, + 'py27': True, + 'commands': 'python setup.py test', + 'deps': '', + } + expected_tox_ini = """ +# Tox (http://tox.testrun.org/) is a tool for running tests +# in multiple virtualenvs. This configuration file will run the +# test suite on all supported python versions. To use it, "pip install tox" +# and then run "tox" from this directory. + +[tox] +envlist = py26, py27 + +[testenv] +commands = python setup.py test +deps = + +""".lstrip() + d = tox._quickstart.process_input(d) + tox._quickstart.generate(d) + result = open('tox.ini').read() + # print(result) + assert(result == expected_tox_ini) + + def test_trial(self, tmpdir): + d = { + 'py27': True, + 'commands': 'trial', + 'deps': 'Twisted', + } + expected_tox_ini = """ +# Tox (http://tox.testrun.org/) is a tool for running tests +# in multiple virtualenvs. This configuration file will run the +# test suite on all supported python versions. To use it, "pip install tox" +# and then run "tox" from this directory. + +[tox] +envlist = py27 + +[testenv] +commands = trial +deps = + Twisted +""".lstrip() + d = tox._quickstart.process_input(d) + tox._quickstart.generate(d) + result = open('tox.ini').read() + # print(result) + assert(result == expected_tox_ini) + + def test_nosetests(self, tmpdir): + d = { + 'py27': True, + 'py32': True, + 'py33': True, + 'pypy': True, + 'commands': 'nosetests -v', + 'deps': 'nose', + } + expected_tox_ini = """ +# Tox (http://tox.testrun.org/) is a tool for running tests +# in multiple virtualenvs. This configuration file will run the +# test suite on all supported python versions. To use it, "pip install tox" +# and then run "tox" from this directory. + +[tox] +envlist = py27, py32, py33, pypy + +[testenv] +commands = nosetests -v +deps = + nose +""".lstrip() + d = tox._quickstart.process_input(d) + tox._quickstart.generate(d) + result = open('tox.ini').read() + # print(result) + assert(result == expected_tox_ini) diff --git a/tox/_quickstart.py b/tox/_quickstart.py new file mode 100644 index 0000000..f8ff64d --- /dev/null +++ b/tox/_quickstart.py @@ -0,0 +1,255 @@ +# -*- coding: utf-8 -*- +""" + tox._quickstart + ~~~~~~~~~~~~~~~~~ + + Command-line script to quickly setup tox.ini for a Python project + + This file was heavily inspired by and uses code from ``sphinx-quickstart`` + in the BSD-licensed `Sphinx project`_. + + .. Sphinx project_: http://sphinx.pocoo.org/ + + License for Sphinx + ================== + + Copyright (c) 2007-2011 by the Sphinx team (see AUTHORS file). + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are + met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +""" + +import sys +from os import path +from codecs import open + +TERM_ENCODING = getattr(sys.stdin, 'encoding', None) + +from tox import __version__ + +# function to get input from terminal -- overridden by the test suite +try: + # this raw_input is not converted by 2to3 + term_input = raw_input +except NameError: + term_input = input + + +all_envs = ['py24', 'py25', 'py26', 'py27', 'py30', 'py31', 'py32', 'py33', 'pypy', 'jython'] + +PROMPT_PREFIX = '> ' + +QUICKSTART_CONF = '''\ +# Tox (http://tox.testrun.org/) is a tool for running tests +# in multiple virtualenvs. This configuration file will run the +# test suite on all supported python versions. To use it, "pip install tox" +# and then run "tox" from this directory. + +[tox] +envlist = %(envlist)s + +[testenv] +commands = %(commands)s +deps = %(deps)s +''' + + +class ValidationError(Exception): + """Raised for validation errors.""" + +def nonempty(x): + if not x: + raise ValidationError("Please enter some text.") + return x + +def choice(*l): + def val(x): + if x not in l: + raise ValidationError('Please enter one of %s.' % ', '.join(l)) + return x + return val + +def boolean(x): + if x.upper() not in ('Y', 'YES', 'N', 'NO'): + raise ValidationError("Please enter either 'y' or 'n'.") + return x.upper() in ('Y', 'YES') + +def suffix(x): + if not (x[0:1] == '.' and len(x) > 1): + raise ValidationError("Please enter a file suffix, " + "e.g. '.rst' or '.txt'.") + return x + +def ok(x): + return x + + +def do_prompt(d, key, text, default=None, validator=nonempty): + while True: + if default: + prompt = PROMPT_PREFIX + '%s [%s]: ' % (text, default) + else: + prompt = PROMPT_PREFIX + text + ': ' + x = term_input(prompt) + if default and not x: + x = default + if sys.version_info < (3, ) and not isinstance(x, unicode): + # for Python 2.x, try to get a Unicode string out of it + if x.decode('ascii', 'replace').encode('ascii', 'replace') != x: + if TERM_ENCODING: + x = x.decode(TERM_ENCODING) + else: + print('* Note: non-ASCII characters entered ' + 'and terminal encoding unknown -- assuming ' + 'UTF-8 or Latin-1.') + try: + x = x.decode('utf-8') + except UnicodeDecodeError: + x = x.decode('latin1') + try: + x = validator(x) + except ValidationError: + err = sys.exc_info()[1] + print('* ' + str(err)) + continue + break + d[key] = x + + +def ask_user(d): + """Ask the user for quickstart values missing from *d*. + + """ + + print('Welcome to the Tox %s quickstart utility.' % __version__) + print(''' +This utility will ask you a few questions and then generate a simple tox.ini +file to help get you started using tox. + +Please enter values for the following settings (just press Enter to +accept a default value, if one is given in brackets).''') + + sys.stdout.write('\n') + + print(''' +What Python versions do you want to test against? Choices: + [1] py27 + [2] py27, py33 + [3] (All versions) %s + [4] Choose each one-by-one''' % ', '.join(all_envs)) + do_prompt(d, 'canned_pyenvs', 'Enter the number of your choice', + '3', choice('1', '2', '3', '4')) + + if d['canned_pyenvs'] == '1': + d['py27'] = True + elif d['canned_pyenvs'] == '2': + for pyenv in ('py27', 'py33'): + d[pyenv] = True + elif d['canned_pyenvs'] == '3': + for pyenv in all_envs: + d[pyenv] = True + elif d['canned_pyenvs'] == '4': + for pyenv in all_envs: + if pyenv not in d: + do_prompt(d, pyenv, 'Test your project with %s (Y/n)' % pyenv, 'Y', boolean) + + print(''' +What command should be used to test your project -- examples: + - py.test + - python setup.py test + - nosetests package.module + - trial package.module''') + do_prompt(d, 'commands', 'Command to run to test project', '{envpython} setup.py test') + + default_deps = ' ' + if 'py.test' in d['commands']: + default_deps = 'pytest' + if 'nosetests' in d['commands']: + default_deps = 'nose' + if 'trial' in d['commands']: + default_deps = 'twisted' + + print(''' +What dependencies does your project have?''') + do_prompt(d, 'deps', 'Comma-separated list of dependencies', default_deps) + + +def process_input(d): + d['envlist'] = ', '.join([env for env in all_envs if d.get(env) is True]) + d['deps'] = '\n' + '\n'.join([' %s' % dep.strip() for dep in d['deps'].split(',')]) + + return d + + +def generate(d, overwrite=True, silent=False): + """Generate project based on values in *d*.""" + + conf_text = QUICKSTART_CONF % d + + def write_file(fpath, mode, content): + if overwrite or not path.isfile(fpath): + print('Creating file %s.' % fpath) + f = open(fpath, mode, encoding='utf-8') + try: + f.write(content) + finally: + f.close() + else: + print('File %s already exists, skipping.' % fpath) + + sys.stdout.write('\n') + + write_file('tox.ini', 'w', conf_text) + + if silent: + return + sys.stdout.write('\n') + print('Finished: A tox.ini file has been created. For information on this file, see http://tox.testrun.org/latest/config.html') + print(''' +Execute `tox` to test your project. +''') + + +def main(argv=sys.argv): + d = {} + + if len(argv) > 3: + print('Usage: tox-quickstart [root]') + sys.exit(1) + elif len(argv) == 2: + d['path'] = argv[1] + + try: + ask_user(d) + except (KeyboardInterrupt, EOFError): + print() + print('[Interrupted.]') + return + + d = process_input(d) + generate(d) + + +if __name__ == '__main__': + main() |
