summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorholger krekel <holger.krekel@gmail.com>2012-11-24 20:05:29 +0100
committerholger krekel <holger.krekel@gmail.com>2012-11-24 20:05:29 +0100
commit6cac5b2a023599a474ff819eb0b6da6be3800570 (patch)
treeb1ed12619504bcf52d634a8f5c64eac41c3f5d89
parent3e20ed7a4fa80f685c515bcda66eac1b647f02ca (diff)
parentc25ff31f0214c02574fe4f9124f2568cb36b7ff5 (diff)
downloadtox-6cac5b2a023599a474ff819eb0b6da6be3800570.tar.gz
Merged in msabramo/tox_quickstart (pull request #25)
-rwxr-xr-xCHANGELOG3
-rw-r--r--CONTRIBUTORS1
-rw-r--r--setup.py2
-rw-r--r--tests/conftest.py290
-rw-r--r--tox/__init__.py2
-rw-r--r--tox/_pytestplugin.py284
-rw-r--r--toxbootstrap.py2
7 files changed, 292 insertions, 292 deletions
diff --git a/CHANGELOG b/CHANGELOG
index 3468c79..3df2a25 100755
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,6 +1,9 @@
1.4.3.dev
-----------------
+- merged tox-quickstart command, contributed by Marc Abramowitz, which
+ generates a default tox.ini after asking a few questions
+
- fix #48 - win32 detection of pypy and other interpreters that are on PATH
(thanks Gustavo Picon)
diff --git a/CONTRIBUTORS b/CONTRIBUTORS
index 74a1047..e8133fc 100644
--- a/CONTRIBUTORS
+++ b/CONTRIBUTORS
@@ -1,6 +1,7 @@
contributions (under the MIT license):
+Marc Abramowitz
Sridhar Ratnakumar
Chris Rose
Jannis Leidl
diff --git a/setup.py b/setup.py
index a64d111..69ba8d3 100644
--- a/setup.py
+++ b/setup.py
@@ -49,7 +49,7 @@ def main():
description='virtualenv-based automation of test activities',
long_description=long_description,
url='http://tox.testrun.org/',
- version='1.4.3.dev1',
+ version='1.4.3.dev2',
license='GPLv2 or later',
platforms=['unix', 'linux', 'osx', 'cygwin', 'win32'],
author='holger krekel',
diff --git a/tests/conftest.py b/tests/conftest.py
index 2f33022..1d4bdde 100644
--- a/tests/conftest.py
+++ b/tests/conftest.py
@@ -1,290 +1,2 @@
-import py
-import tox
-import os
-import sys
-from py.builtin import print_
-from fnmatch import fnmatch
-import time
-from tox._config import parseconfig
-from tox._venv import VirtualEnv
-from tox._cmdline import Action
-def pytest_configure():
- if 'TOXENV' in os.environ:
- del os.environ['TOXENV']
- if 'HUDSON_URL' in os.environ:
- del os.environ['HUDSON_URL']
-
-def pytest_report_header():
- return "tox comes from: %r" % (tox.__file__)
-
-def pytest_funcarg__newconfig(request):
- tmpdir = request.getfuncargvalue("tmpdir")
- def newconfig(args, source=None):
- if source is None:
- source = args
- args = []
- s = py.std.textwrap.dedent(source)
- p = tmpdir.join("tox.ini")
- p.write(s)
- old = tmpdir.chdir()
- try:
- return parseconfig(args)
- finally:
- old.chdir()
- return newconfig
-
-def pytest_funcarg__tmpdir(request):
- tmpdir = request.getfuncargvalue("tmpdir")
- request.addfinalizer(py.path.local().chdir)
- tmpdir.chdir()
- return tmpdir
-
-def pytest_funcarg__cmd(request):
- return Cmd(request)
-
-class ReportExpectMock:
- def __init__(self, session):
- self._calls = []
- self._index = -1
- self.session = session
-
- def clear(self):
- self._calls[:] = []
-
- def __getattr__(self, name):
- if name[0] == "_":
- raise AttributeError(name)
-
- def generic_report(*args, **kwargs):
- self._calls.append((name,)+args)
- print ("%s" %(self._calls[-1], ))
- return generic_report
-
- def action(self, venv, msg, *args):
- self._calls.append(("action", venv, msg))
- print ("%s" %(self._calls[-1], ))
- return Action(self.session, venv, msg, args)
-
- def getnext(self, cat):
- __tracebackhide__ = True
- newindex = self._index + 1
- while newindex < len(self._calls):
- call = self._calls[newindex]
- lcat = call[0]
- if fnmatch(lcat, cat):
- self._index = newindex
- return call
- newindex += 1
- raise LookupError(
- "looking for %r, no reports found at >=%d in %r" %
- (cat, self._index+1, self._calls))
-
- def expect(self, cat, messagepattern="*", invert=False):
- __tracebackhide__ = True
- if not messagepattern.startswith("*"):
- messagepattern = "*" + messagepattern
- while self._index < len(self._calls):
- try:
- call = self.getnext(cat)
- except LookupError:
- break
- for lmsg in call[1:]:
- lmsg = str(lmsg).replace("\n", " ")
- if fnmatch(lmsg, messagepattern):
- if invert:
- raise AssertionError("found %s(%r), didn't expect it" %
- (cat, messagepattern))
- return
- if not invert:
- raise AssertionError(
- "looking for %s(%r), no reports found at >=%d in %r" %
- (cat, messagepattern, self._index+1, self._calls))
-
- def not_expect(self, cat, messagepattern="*"):
- return self.expect(cat, messagepattern, invert=True)
-
-class pcallMock:
- def __init__(self, args, cwd, env, stdout, stderr, shell):
- self.arg0 = args[0]
- self.args = args[1:]
- self.cwd = cwd
- self.env = env
- self.stdout = stdout
- self.stderr = stderr
- self.shell = shell
-
- def communicate(self):
- return "", ""
- def wait(self):
- pass
-
-def pytest_funcarg__mocksession(request):
- from tox._cmdline import Session
- class MockSession(Session):
- def __init__(self):
- self._clearmocks()
- self.config = request.getfuncargvalue("newconfig")([], "")
- self._actions = []
- def getenv(self, name):
- return VirtualEnv(self.config.envconfigs[name], session=self)
- def _clearmocks(self):
- self._pcalls = []
- self._spec2pkg = {}
- self.report = ReportExpectMock(self)
- def make_emptydir(self, path):
- pass
- def popen(self, args, cwd, shell=None,
- stdout=None, stderr=None, env=None):
- pm = pcallMock(args, cwd, env, stdout, stderr, shell)
- self._pcalls.append(pm)
- return pm
- return MockSession()
-
-def pytest_funcarg__newmocksession(request):
- mocksession = request.getfuncargvalue("mocksession")
- newconfig = request.getfuncargvalue("newconfig")
- def newmocksession(args, source):
- config = newconfig(args, source)
- mocksession.config = config
- return mocksession
- return newmocksession
-
-class Cmd:
- def __init__(self, request):
- self.tmpdir = request.getfuncargvalue("tmpdir")
- self.request = request
- current = py.path.local()
- self.request.addfinalizer(current.chdir)
- def chdir(self, target):
- target.chdir()
-
- def popen(self, argv, stdout, stderr, **kw):
- if not hasattr(py.std, 'subprocess'):
- py.test.skip("no subprocess module")
- env = os.environ.copy()
- env['PYTHONPATH'] = ":".join(filter(None, [
- str(os.getcwd()), env.get('PYTHONPATH', '')]))
- kw['env'] = env
- #print "env", env
- return py.std.subprocess.Popen(argv, stdout=stdout, stderr=stderr, **kw)
-
- def run(self, *argv):
- argv = [str(x) for x in argv]
- p1 = self.tmpdir.join("stdout")
- p2 = self.tmpdir.join("stderr")
- print("%s$ %s" % (os.getcwd(), " ".join(argv)))
- f1 = p1.open("wb")
- f2 = p2.open("wb")
- now = time.time()
- popen = self.popen(argv, stdout=f1, stderr=f2,
- close_fds=(sys.platform != "win32"))
- ret = popen.wait()
- f1.close()
- f2.close()
- out = p1.read("rb")
- out = getdecoded(out).splitlines()
- err = p2.read("rb")
- err = getdecoded(err).splitlines()
- def dump_lines(lines, fp):
- try:
- for line in lines:
- py.builtin.print_(line, file=fp)
- except UnicodeEncodeError:
- print("couldn't print to %s because of encoding" % (fp,))
- dump_lines(out, sys.stdout)
- dump_lines(err, sys.stderr)
- return RunResult(ret, out, err, time.time()-now)
-
-def getdecoded(out):
- try:
- return out.decode("utf-8")
- except UnicodeDecodeError:
- return "INTERNAL not-utf8-decodeable, truncated string:\n%s" % (
- py.io.saferepr(out),)
-
-class RunResult:
- def __init__(self, ret, outlines, errlines, duration):
- self.ret = ret
- self.outlines = outlines
- self.errlines = errlines
- self.stdout = LineMatcher(outlines)
- self.stderr = LineMatcher(errlines)
- self.duration = duration
-
-class LineMatcher:
- def __init__(self, lines):
- self.lines = lines
-
- def str(self):
- return "\n".join(self.lines)
-
- def fnmatch_lines(self, lines2):
- if isinstance(lines2, str):
- lines2 = py.code.Source(lines2)
- if isinstance(lines2, py.code.Source):
- lines2 = lines2.strip().lines
-
- from fnmatch import fnmatch
- lines1 = self.lines[:]
- nextline = None
- extralines = []
- __tracebackhide__ = True
- for line in lines2:
- nomatchprinted = False
- while lines1:
- nextline = lines1.pop(0)
- if line == nextline:
- print_("exact match:", repr(line))
- break
- elif fnmatch(nextline, line):
- print_("fnmatch:", repr(line))
- print_(" with:", repr(nextline))
- break
- else:
- if not nomatchprinted:
- print_("nomatch:", repr(line))
- nomatchprinted = True
- print_(" and:", repr(nextline))
- extralines.append(nextline)
- else:
- assert line == nextline
-
-def pytest_funcarg__initproj(request):
- """ create a factory function for creating example projects. """
- tmpdir = request.getfuncargvalue("tmpdir")
- def initproj(name, filedefs=None):
- if filedefs is None:
- filedefs = {}
- parts = name.split("-")
- if len(parts) == 1:
- parts.append("0.1")
- name, version = parts
- base = tmpdir.ensure(name, dir=1)
- create_files(base, filedefs)
- if 'setup.py' not in filedefs:
- create_files(base, {'setup.py': '''
- from setuptools import setup
- setup(
- name='%(name)s',
- description='%(name)s project',
- version='%(version)s',
- license='GPLv2 or later',
- platforms=['unix', 'win32'],
- packages=['%(name)s', ],
- )
- ''' % locals()})
- if name not in filedefs:
- create_files(base, {name:
- {'__init__.py': '__version__ = %s' % version}})
- print ("created project in %s" %(base,))
- base.chdir()
- return initproj
-
-def create_files(base, filedefs):
- for key, value in filedefs.items():
- if isinstance(value, dict):
- create_files(base.ensure(key, dir=1), value)
- elif isinstance(value, str):
- s = py.std.textwrap.dedent(value)
- base.join(key).write(s)
+from tox._pytestplugin import *
diff --git a/tox/__init__.py b/tox/__init__.py
index e6669b6..ca98634 100644
--- a/tox/__init__.py
+++ b/tox/__init__.py
@@ -1,5 +1,5 @@
#
-__version__ = '1.4.3.dev1'
+__version__ = '1.4.3.dev2'
class exception:
class Error(Exception):
diff --git a/tox/_pytestplugin.py b/tox/_pytestplugin.py
new file mode 100644
index 0000000..fc913d6
--- /dev/null
+++ b/tox/_pytestplugin.py
@@ -0,0 +1,284 @@
+import pytest, py
+import tox
+import os
+import sys
+from py.builtin import print_
+from fnmatch import fnmatch
+import time
+from tox._config import parseconfig
+from tox._venv import VirtualEnv
+from tox._cmdline import Action
+
+def pytest_configure():
+ if 'TOXENV' in os.environ:
+ del os.environ['TOXENV']
+ if 'HUDSON_URL' in os.environ:
+ del os.environ['HUDSON_URL']
+
+def pytest_report_header():
+ return "tox comes from: %r" % (tox.__file__)
+
+def pytest_funcarg__newconfig(request):
+ tmpdir = request.getfuncargvalue("tmpdir")
+ def newconfig(args, source=None):
+ if source is None:
+ source = args
+ args = []
+ s = py.std.textwrap.dedent(source)
+ p = tmpdir.join("tox.ini")
+ p.write(s)
+ old = tmpdir.chdir()
+ try:
+ return parseconfig(args)
+ finally:
+ old.chdir()
+ return newconfig
+
+def pytest_funcarg__cmd(request):
+ return Cmd(request)
+
+class ReportExpectMock:
+ def __init__(self, session):
+ self._calls = []
+ self._index = -1
+ self.session = session
+
+ def clear(self):
+ self._calls[:] = []
+
+ def __getattr__(self, name):
+ if name[0] == "_":
+ raise AttributeError(name)
+
+ def generic_report(*args, **kwargs):
+ self._calls.append((name,)+args)
+ print ("%s" %(self._calls[-1], ))
+ return generic_report
+
+ def action(self, venv, msg, *args):
+ self._calls.append(("action", venv, msg))
+ print ("%s" %(self._calls[-1], ))
+ return Action(self.session, venv, msg, args)
+
+ def getnext(self, cat):
+ __tracebackhide__ = True
+ newindex = self._index + 1
+ while newindex < len(self._calls):
+ call = self._calls[newindex]
+ lcat = call[0]
+ if fnmatch(lcat, cat):
+ self._index = newindex
+ return call
+ newindex += 1
+ raise LookupError(
+ "looking for %r, no reports found at >=%d in %r" %
+ (cat, self._index+1, self._calls))
+
+ def expect(self, cat, messagepattern="*", invert=False):
+ __tracebackhide__ = True
+ if not messagepattern.startswith("*"):
+ messagepattern = "*" + messagepattern
+ while self._index < len(self._calls):
+ try:
+ call = self.getnext(cat)
+ except LookupError:
+ break
+ for lmsg in call[1:]:
+ lmsg = str(lmsg).replace("\n", " ")
+ if fnmatch(lmsg, messagepattern):
+ if invert:
+ raise AssertionError("found %s(%r), didn't expect it" %
+ (cat, messagepattern))
+ return
+ if not invert:
+ raise AssertionError(
+ "looking for %s(%r), no reports found at >=%d in %r" %
+ (cat, messagepattern, self._index+1, self._calls))
+
+ def not_expect(self, cat, messagepattern="*"):
+ return self.expect(cat, messagepattern, invert=True)
+
+class pcallMock:
+ def __init__(self, args, cwd, env, stdout, stderr, shell):
+ self.arg0 = args[0]
+ self.args = args[1:]
+ self.cwd = cwd
+ self.env = env
+ self.stdout = stdout
+ self.stderr = stderr
+ self.shell = shell
+
+ def communicate(self):
+ return "", ""
+ def wait(self):
+ pass
+
+def pytest_funcarg__mocksession(request):
+ from tox._cmdline import Session
+ class MockSession(Session):
+ def __init__(self):
+ self._clearmocks()
+ self.config = request.getfuncargvalue("newconfig")([], "")
+ self._actions = []
+ def getenv(self, name):
+ return VirtualEnv(self.config.envconfigs[name], session=self)
+ def _clearmocks(self):
+ self._pcalls = []
+ self._spec2pkg = {}
+ self.report = ReportExpectMock(self)
+ def make_emptydir(self, path):
+ pass
+ def popen(self, args, cwd, shell=None,
+ stdout=None, stderr=None, env=None):
+ pm = pcallMock(args, cwd, env, stdout, stderr, shell)
+ self._pcalls.append(pm)
+ return pm
+ return MockSession()
+
+def pytest_funcarg__newmocksession(request):
+ mocksession = request.getfuncargvalue("mocksession")
+ newconfig = request.getfuncargvalue("newconfig")
+ def newmocksession(args, source):
+ config = newconfig(args, source)
+ mocksession.config = config
+ return mocksession
+ return newmocksession
+
+class Cmd:
+ def __init__(self, request):
+ self.tmpdir = request.getfuncargvalue("tmpdir")
+ self.request = request
+ current = py.path.local()
+ self.request.addfinalizer(current.chdir)
+ def chdir(self, target):
+ target.chdir()
+
+ def popen(self, argv, stdout, stderr, **kw):
+ if not hasattr(py.std, 'subprocess'):
+ py.test.skip("no subprocess module")
+ env = os.environ.copy()
+ env['PYTHONPATH'] = ":".join(filter(None, [
+ str(os.getcwd()), env.get('PYTHONPATH', '')]))
+ kw['env'] = env
+ #print "env", env
+ return py.std.subprocess.Popen(argv, stdout=stdout, stderr=stderr, **kw)
+
+ def run(self, *argv):
+ argv = [str(x) for x in argv]
+ p1 = self.tmpdir.join("stdout")
+ p2 = self.tmpdir.join("stderr")
+ print("%s$ %s" % (os.getcwd(), " ".join(argv)))
+ f1 = p1.open("wb")
+ f2 = p2.open("wb")
+ now = time.time()
+ popen = self.popen(argv, stdout=f1, stderr=f2,
+ close_fds=(sys.platform != "win32"))
+ ret = popen.wait()
+ f1.close()
+ f2.close()
+ out = p1.read("rb")
+ out = getdecoded(out).splitlines()
+ err = p2.read("rb")
+ err = getdecoded(err).splitlines()
+ def dump_lines(lines, fp):
+ try:
+ for line in lines:
+ py.builtin.print_(line, file=fp)
+ except UnicodeEncodeError:
+ print("couldn't print to %s because of encoding" % (fp,))
+ dump_lines(out, sys.stdout)
+ dump_lines(err, sys.stderr)
+ return RunResult(ret, out, err, time.time()-now)
+
+def getdecoded(out):
+ try:
+ return out.decode("utf-8")
+ except UnicodeDecodeError:
+ return "INTERNAL not-utf8-decodeable, truncated string:\n%s" % (
+ py.io.saferepr(out),)
+
+class RunResult:
+ def __init__(self, ret, outlines, errlines, duration):
+ self.ret = ret
+ self.outlines = outlines
+ self.errlines = errlines
+ self.stdout = LineMatcher(outlines)
+ self.stderr = LineMatcher(errlines)
+ self.duration = duration
+
+class LineMatcher:
+ def __init__(self, lines):
+ self.lines = lines
+
+ def str(self):
+ return "\n".join(self.lines)
+
+ def fnmatch_lines(self, lines2):
+ if isinstance(lines2, str):
+ lines2 = py.code.Source(lines2)
+ if isinstance(lines2, py.code.Source):
+ lines2 = lines2.strip().lines
+
+ from fnmatch import fnmatch
+ lines1 = self.lines[:]
+ nextline = None
+ extralines = []
+ __tracebackhide__ = True
+ for line in lines2:
+ nomatchprinted = False
+ while lines1:
+ nextline = lines1.pop(0)
+ if line == nextline:
+ print_("exact match:", repr(line))
+ break
+ elif fnmatch(nextline, line):
+ print_("fnmatch:", repr(line))
+ print_(" with:", repr(nextline))
+ break
+ else:
+ if not nomatchprinted:
+ print_("nomatch:", repr(line))
+ nomatchprinted = True
+ print_(" and:", repr(nextline))
+ extralines.append(nextline)
+ else:
+ assert line == nextline
+
+@pytest.fixture
+def initproj(request, tmpdir):
+ """ create a factory function for creating example projects. """
+ def initproj(name, filedefs=None):
+ if filedefs is None:
+ filedefs = {}
+ parts = name.split("-")
+ if len(parts) == 1:
+ parts.append("0.1")
+ name, version = parts
+ base = tmpdir.ensure(name, dir=1)
+ create_files(base, filedefs)
+ if 'setup.py' not in filedefs:
+ create_files(base, {'setup.py': '''
+ from setuptools import setup
+ setup(
+ name='%(name)s',
+ description='%(name)s project',
+ version='%(version)s',
+ license='GPLv2 or later',
+ platforms=['unix', 'win32'],
+ packages=['%(name)s', ],
+ )
+ ''' % locals()})
+ if name not in filedefs:
+ create_files(base, {name:
+ {'__init__.py': '__version__ = %s' % version}})
+ print ("created project in %s" %(base,))
+ base.chdir()
+ return initproj
+
+def create_files(base, filedefs):
+ for key, value in filedefs.items():
+ if isinstance(value, dict):
+ create_files(base.ensure(key, dir=1), value)
+ elif isinstance(value, str):
+ s = py.std.textwrap.dedent(value)
+ base.join(key).write(s)
diff --git a/toxbootstrap.py b/toxbootstrap.py
index 979ea6a..c0cafc2 100644
--- a/toxbootstrap.py
+++ b/toxbootstrap.py
@@ -58,7 +58,7 @@ ToDo
"""
-__version__ = '1.4.3.dev1'
+__version__ = '1.4.3.dev2'
import sys
import os