9 new commits in tox:

https://bitbucket.org/hpk42/tox/commits/14d597656e37/
Changeset:   14d597656e37
User:        mordred
Date:        2013-07-10 22:22:16
Summary:     Add option to skip sdist step.

First change in a sequence to allow for customization of operational
steps. The sdist creation is current unconditional, which for some
projects makes running tests unreasonably slow. For instance, OpenStack
would prefer to just have python setup.py develop run - but we'd like
to put in the support in a flexible way that will allow people to
express the pipeline needs of their project.
Affected #:  4 files

diff -r 63d37ba9cc8babe926e45f9e8294841148b0451b -r 
14d597656e378d1abd515bf90076704824b0f9fe doc/config.txt
--- a/doc/config.txt
+++ b/doc/config.txt
@@ -21,6 +21,7 @@
     distdir=path      # defaults to {toxworkdir}/dist
     distshare=path    # defaults to {homedir}/.tox/distshare
     envlist=ENVLIST   # defaults to the list of all environments
+    skipsdist=BOOL    # defaults to false
 
 
 ``tox`` autodetects if it is running in a Jenkins_ context

diff -r 63d37ba9cc8babe926e45f9e8294841148b0451b -r 
14d597656e378d1abd515bf90076704824b0f9fe tests/test_z_cmdline.py
--- a/tests/test_z_cmdline.py
+++ b/tests/test_z_cmdline.py
@@ -252,6 +252,23 @@
         "*ERROR*unknown*environment*qpwoei*",
     ])
 
+def test_skip_sdist(cmd, initproj):
+    initproj("pkg123-0.7", filedefs={
+        'tests': {'test_hello.py': "def test_hello(): pass"},
+        'setup.py': """
+            syntax error
+        """
+        ,
+        'tox.ini': '''
+            [tox]
+            skipsdist=True
+            [testenv]
+            commands=echo done
+        '''
+    })
+    result = cmd.run("tox", )
+    assert result.ret == 0
+
 def test_sdist_fails(cmd, initproj):
     initproj("pkg123-0.7", filedefs={
         'tests': {'test_hello.py': "def test_hello(): pass"},

diff -r 63d37ba9cc8babe926e45f9e8294841148b0451b -r 
14d597656e378d1abd515bf90076704824b0f9fe tox/_cmdline.py
--- a/tox/_cmdline.py
+++ b/tox/_cmdline.py
@@ -362,19 +362,24 @@
         return sdist_path
 
     def subcommand_test(self):
-        sdist_path = self.sdist()
-        if not sdist_path:
-            return 2
+        if self.config.skipsdist:
+            self.report.info("skipping sdist step")
+            sdist_path = None
+        else:
+            sdist_path = self.sdist()
+            if not sdist_path:
+                return 2
         if self.config.option.sdistonly:
             return
         for venv in self.venvlist:
             if self.setupenv(venv):
-                self.installpkg(venv, sdist_path)
-                self.runtestenv(venv, sdist_path)
+                if not self.config.skipsdist:
+                    self.installpkg(venv, sdist_path)
+                self.runtestenv(venv)
         retcode = self._summary()
         return retcode
 
-    def runtestenv(self, venv, sdist_path, redirect=False):
+    def runtestenv(self, venv, redirect=False):
         if not self.config.option.notest:
             if venv.status:
                 return
@@ -408,6 +413,7 @@
         self.report.keyvalue("toxworkdir: ", self.config.toxworkdir)
         self.report.keyvalue("setupdir:   ", self.config.setupdir)
         self.report.keyvalue("distshare:  ", self.config.distshare)
+        self.report.keyvalue("skipsdist:  ", self.config.skipsdist)
         self.report.tw.line()
         for envconfig in self.config.envconfigs.values():
             self.report.line("[testenv:%s]" % envconfig.envname, bold=True)

diff -r 63d37ba9cc8babe926e45f9e8294841148b0451b -r 
14d597656e378d1abd515bf90076704824b0f9fe tox/_config.py
--- a/tox/_config.py
+++ b/tox/_config.py
@@ -194,6 +194,7 @@
                               homedir=config.homedir)
         config.toxworkdir = reader.getpath(toxsection, "toxworkdir",
                                            "{toxinidir}/.tox")
+        config.skipsdist = reader.getbool(toxsection, "skipsdist", False)
         config.minversion = reader.getdefault(toxsection, "minversion", None)
 
         # determine indexserver dictionary


https://bitbucket.org/hpk42/tox/commits/517fca71add7/
Changeset:   517fca71add7
User:        mordred
Date:        2013-07-10 22:44:42
Summary:     Make sure that the venv is finalized.

Skipping sdist causes the config to not be saved, which causes
recreation next time.
Affected #:  2 files

diff -r 14d597656e378d1abd515bf90076704824b0f9fe -r 
517fca71add7ed6d191ce04206109c6eceabc58d tox/_cmdline.py
--- a/tox/_cmdline.py
+++ b/tox/_cmdline.py
@@ -327,6 +327,12 @@
                 return False
             return True
 
+    def finishvenv(self, venv):
+        action = self.newaction(venv, "finishvenv")
+        with action:
+            venv.finish()
+            return True
+
     def installpkg(self, venv, sdist_path):
         action = self.newaction(venv, "installpkg", sdist_path)
         with action:
@@ -375,6 +381,8 @@
             if self.setupenv(venv):
                 if not self.config.skipsdist:
                     self.installpkg(venv, sdist_path)
+                else:
+                    self.finishvenv(venv)
                 self.runtestenv(venv)
         retcode = self._summary()
         return retcode

diff -r 14d597656e378d1abd515bf90076704824b0f9fe -r 
517fca71add7ed6d191ce04206109c6eceabc58d tox/_venv.py
--- a/tox/_venv.py
+++ b/tox/_venv.py
@@ -197,11 +197,14 @@
         self._pcall(args, venv=False, action=action, cwd=basepath)
         self.just_created = True
 
+    def finish(self):
+        self._getliveconfig().writeconfig(self.path_config)
+
     def installpkg(self, sdistpath, action):
         assert action is not None
         if getattr(self, 'just_created', False):
             action.setactivity("inst", sdistpath)
-            self._getliveconfig().writeconfig(self.path_config)
+            self.finish()
             extraopts = []
         else:
             action.setactivity("inst-nodeps", sdistpath)


https://bitbucket.org/hpk42/tox/commits/5464e3062afa/
Changeset:   5464e3062afa
User:        mordred
Date:        2013-07-10 23:41:45
Summary:     Add support for installing via setup.py develop.
Affected #:  4 files

diff -r 517fca71add7ed6d191ce04206109c6eceabc58d -r 
5464e3062afa62ef2731fcc63902041adaffa56f doc/config.txt
--- a/doc/config.txt
+++ b/doc/config.txt
@@ -22,6 +22,7 @@
     distshare=path    # defaults to {homedir}/.tox/distshare
     envlist=ENVLIST   # defaults to the list of all environments
     skipsdist=BOOL    # defaults to false
+    usedevelop=BOOL   # use python setup.py develop, defaults to false
 
 
 ``tox`` autodetects if it is running in a Jenkins_ context

diff -r 517fca71add7ed6d191ce04206109c6eceabc58d -r 
5464e3062afa62ef2731fcc63902041adaffa56f tox/_cmdline.py
--- a/tox/_cmdline.py
+++ b/tox/_cmdline.py
@@ -333,6 +333,16 @@
             venv.finish()
             return True
 
+    def developpkg(self, venv, setupdir):
+        action = self.newaction(venv, "developpkg", setupdir)
+        with action:
+            try:
+                venv.developpkg(setupdir, action)
+                return True
+            except tox.exception.InvocationError:
+                venv.status = sys.exc_info()[1]
+                return False
+
     def installpkg(self, venv, sdist_path):
         action = self.newaction(venv, "installpkg", sdist_path)
         with action:
@@ -379,10 +389,12 @@
             return
         for venv in self.venvlist:
             if self.setupenv(venv):
-                if not self.config.skipsdist:
+                if self.config.skipsdist:
+                    if self.config.usedevelop:
+                        self.developpkg(venv, self.config.setupdir)
+                    self.finishvenv(venv)
+                else:
                     self.installpkg(venv, sdist_path)
-                else:
-                    self.finishvenv(venv)
                 self.runtestenv(venv)
         retcode = self._summary()
         return retcode
@@ -422,6 +434,7 @@
         self.report.keyvalue("setupdir:   ", self.config.setupdir)
         self.report.keyvalue("distshare:  ", self.config.distshare)
         self.report.keyvalue("skipsdist:  ", self.config.skipsdist)
+        self.report.keyvalue("usedevelop: ", self.config.usedevelop)
         self.report.tw.line()
         for envconfig in self.config.envconfigs.values():
             self.report.line("[testenv:%s]" % envconfig.envname, bold=True)

diff -r 517fca71add7ed6d191ce04206109c6eceabc58d -r 
5464e3062afa62ef2731fcc63902041adaffa56f tox/_config.py
--- a/tox/_config.py
+++ b/tox/_config.py
@@ -194,7 +194,9 @@
                               homedir=config.homedir)
         config.toxworkdir = reader.getpath(toxsection, "toxworkdir",
                                            "{toxinidir}/.tox")
-        config.skipsdist = reader.getbool(toxsection, "skipsdist", False)
+        config.usedevelop = reader.getbool(toxsection, "usedevelop", False)
+        config.skipsdist = reader.getbool(
+            toxsection, "skipsdist", config.usedevelop)
         config.minversion = reader.getdefault(toxsection, "minversion", None)
 
         # determine indexserver dictionary

diff -r 517fca71add7ed6d191ce04206109c6eceabc58d -r 
5464e3062afa62ef2731fcc63902041adaffa56f tox/_venv.py
--- a/tox/_venv.py
+++ b/tox/_venv.py
@@ -1,4 +1,5 @@
 from __future__ import with_statement
+import subprocess
 import sys, os, re
 import py
 import tox
@@ -200,6 +201,29 @@
     def finish(self):
         self._getliveconfig().writeconfig(self.path_config)
 
+    def _needs_reinstall(self, setupdir, action):
+        setup_py = setupdir.join('setup.py')
+        setup_cfg = setupdir.join('setup.cfg')
+        args = [str(self.getconfigexecutable()), str(setup_py), '--name']
+        output = subprocess.Popen(args, stdout=subprocess.PIPE,
+                                  stderr=subprocess.PIPE)
+        out = output.communicate()
+        name = out[0].strip().decode('utf-8')
+        egg_info = setupdir.join('.'.join((name, 'egg-info')))
+        for conf_file in (setup_py, setup_cfg):
+            if (conf_file.check()
+                    and conf_file.mtime() > egg_info.mtime()):
+                return True
+        return False
+
+    def developpkg(self, setupdir, action):
+        assert action is not None
+        self.finish()
+        if not self._needs_reinstall(setupdir, action):
+            return
+        extraopts = ['--no-deps']
+        self._install(['-e', setupdir], extraopts=extraopts, action=action)
+
     def installpkg(self, sdistpath, action):
         assert action is not None
         if getattr(self, 'just_created', False):


https://bitbucket.org/hpk42/tox/commits/94ec2412ae39/
Changeset:   94ec2412ae39
User:        mordred
Date:        2013-07-11 17:29:51
Summary:     Address code review comments

Use action.popen instead of subprocess.popen.
Allow skipsdist=False and usedevelop=True to coexist.
Affected #:  2 files

diff -r 5464e3062afa62ef2731fcc63902041adaffa56f -r 
94ec2412ae399eb7a75031a412c42e94dc572896 tox/_cmdline.py
--- a/tox/_cmdline.py
+++ b/tox/_cmdline.py
@@ -73,7 +73,7 @@
         f.flush()
         return f
 
-    def popen(self, args, cwd=None, env=None, redirect=True):
+    def popen(self, args, cwd=None, env=None, redirect=True, returnout=False):
         logged_command = "%s$ %s" %(cwd, " ".join(map(str, args)))
         f = outpath = None
         if redirect:
@@ -82,6 +82,8 @@
                     self.id, self.msg, args, env))
             f.flush()
             self.popen_outpath = outpath = py.path.local(f.name)
+        elif returnout:
+            f = subprocess.PIPE
         if cwd is None:
             # XXX cwd = self.session.config.cwd
             cwd = py.path.local()
@@ -389,9 +391,9 @@
             return
         for venv in self.venvlist:
             if self.setupenv(venv):
-                if self.config.skipsdist:
-                    if self.config.usedevelop:
-                        self.developpkg(venv, self.config.setupdir)
+                if self.config.usedevelop:
+                    self.developpkg(venv, self.config.setupdir)
+                elif self.config.skipsdist:
                     self.finishvenv(venv)
                 else:
                     self.installpkg(venv, sdist_path)

diff -r 5464e3062afa62ef2731fcc63902041adaffa56f -r 
94ec2412ae399eb7a75031a412c42e94dc572896 tox/_venv.py
--- a/tox/_venv.py
+++ b/tox/_venv.py
@@ -1,5 +1,4 @@
 from __future__ import with_statement
-import subprocess
 import sys, os, re
 import py
 import tox
@@ -205,10 +204,9 @@
         setup_py = setupdir.join('setup.py')
         setup_cfg = setupdir.join('setup.cfg')
         args = [str(self.getconfigexecutable()), str(setup_py), '--name']
-        output = subprocess.Popen(args, stdout=subprocess.PIPE,
-                                  stderr=subprocess.PIPE)
-        out = output.communicate()
-        name = out[0].strip().decode('utf-8')
+        output = action.popen(args, cwd=setupdir, redirect=False,
+                              returnout=True)
+        name = output.strip().decode('utf-8')
         egg_info = setupdir.join('.'.join((name, 'egg-info')))
         for conf_file in (setup_py, setup_cfg):
             if (conf_file.check()


https://bitbucket.org/hpk42/tox/commits/fea763e691c0/
Changeset:   fea763e691c0
User:        mordred
Date:        2013-07-11 17:36:21
Summary:     Add test to use usedevelop

While we're at it, fix the error that adding the test found.
Affected #:  2 files

diff -r 94ec2412ae399eb7a75031a412c42e94dc572896 -r 
fea763e691c022b6eb2de49e26d5d78462ad8614 tests/test_z_cmdline.py
--- a/tests/test_z_cmdline.py
+++ b/tests/test_z_cmdline.py
@@ -359,6 +359,59 @@
     ])
 
 
+def test_test_develop(cmd, initproj):
+    initproj("example123-0.5", filedefs={
+        'tests': {'test_hello.py': """
+            def test_hello(pytestconfig):
+                pass
+            """,
+        },
+        'tox.ini': '''
+            [tox]
+            usedevelop=True
+            [testenv]
+            changedir=tests
+            commands=
+                py.test --basetemp={envtmpdir} --junitxml=junit-{envname}.xml 
[]
+            deps=pytest
+        '''
+    })
+    result = cmd.run("tox")
+    assert not result.ret
+    result.stdout.fnmatch_lines([
+        "*junit-python.xml*",
+        "*1 passed*",
+    ])
+    result = cmd.run("tox", "-epython", )
+    assert not result.ret
+    result.stdout.fnmatch_lines([
+        "*1 passed*",
+        "*summary*",
+        "*python: commands succeeded"
+    ])
+    # see that things work with a different CWD
+    old = cmd.tmpdir.chdir()
+    result = cmd.run("tox", "-c", "example123/tox.ini")
+    assert not result.ret
+    result.stdout.fnmatch_lines([
+        "*1 passed*",
+        "*summary*",
+        "*python: commands succeeded"
+    ])
+    old.chdir()
+    # see that tests can also fail and retcode is correct
+    testfile = py.path.local("tests").join("test_hello.py")
+    assert testfile.check()
+    testfile.write("def test_fail(): assert 0")
+    result = cmd.run("tox", )
+    assert result.ret
+    result.stdout.fnmatch_lines([
+        "*1 failed*",
+        "*summary*",
+        "*python: *failed*",
+    ])
+
+
 def test_test_piphelp(initproj, cmd):
     initproj("example123", filedefs={'tox.ini': """
         # content of: tox.ini

diff -r 94ec2412ae399eb7a75031a412c42e94dc572896 -r 
fea763e691c022b6eb2de49e26d5d78462ad8614 tox/_venv.py
--- a/tox/_venv.py
+++ b/tox/_venv.py
@@ -209,8 +209,8 @@
         name = output.strip().decode('utf-8')
         egg_info = setupdir.join('.'.join((name, 'egg-info')))
         for conf_file in (setup_py, setup_cfg):
-            if (conf_file.check()
-                    and conf_file.mtime() > egg_info.mtime()):
+            if (not egg_info.check() or (conf_file.check()
+                    and conf_file.mtime() > egg_info.mtime())):
                 return True
         return False
 


https://bitbucket.org/hpk42/tox/commits/6a52c1c93e08/
Changeset:   6a52c1c93e08
User:        mordred
Date:        2013-07-11 17:47:44
Summary:     Add example documentation for usedevelop
Affected #:  1 file

diff -r fea763e691c022b6eb2de49e26d5d78462ad8614 -r 
6a52c1c93e083f760e46f24219a91ba9f69b926f doc/example/general.txt
--- a/doc/example/general.txt
+++ b/doc/example/general.txt
@@ -144,4 +144,37 @@
     [testenv:py27]
     basepython=/my/path/to/python2.7
 
+Avoiding expensive sdist
+------------------------
+
+Some projects are large enough that running and sdist, followed by
+an install everytime can be prohibitively costly. To solve this,
+there are two different options you can add to the ``tox`` section. First,
+you can simply ask tox to please not make an sdist::
+
+    [tox]
+    skipsdist=True
+
+If you do this, your local software package will not be installed into
+the virtualenv. You should probably be ok with that, or take steps
+to deal with it in your commands section::
+
+    [testenv]
+    commands =
+        python setup.py develop
+        py.test
+
+Running setup.py develop is a common enough model that it has its own option::
+
+    [tox]
+    usedevelop=True
+
+Which will set ``skipsdist`` to True and then perform the ``setup.py develop``
+step at the place where ``tox`` normally perfoms the installation of the sdist.
+Specifically, it actually runs ``pip install -e .`` behind the scenes, which
+itself calls ``setup.py develop``.
+
+There is an optimization coded in to not bother re-running the command if
+``$projectname.egg-info`` is newer than ``setup.py`` or ``setup.cfg``.
+
 .. include:: ../links.txt


https://bitbucket.org/hpk42/tox/commits/ddda508fcee1/
Changeset:   ddda508fcee1
User:        mordred
Date:        2013-07-16 16:56:23
Summary:     Add command line option for develop
Affected #:  3 files

diff -r 6a52c1c93e083f760e46f24219a91ba9f69b926f -r 
ddda508fcee1c7f91d465b5420a25b6b2b9554ef tests/test_z_cmdline.py
--- a/tests/test_z_cmdline.py
+++ b/tests/test_z_cmdline.py
@@ -359,7 +359,14 @@
     ])
 
 
-def test_test_develop(cmd, initproj):
+def test_develop(initproj, cmd):
+    initproj("example123", filedefs={'tox.ini': """
+    """})
+    result = cmd.run("tox", "-v", "--develop")
+    assert not result.ret
+    assert "sdist-make" not in result.stdout.str()
+
+def test_test_usedevelop(cmd, initproj):
     initproj("example123-0.5", filedefs={
         'tests': {'test_hello.py': """
             def test_hello(pytestconfig):
@@ -376,12 +383,13 @@
             deps=pytest
         '''
     })
-    result = cmd.run("tox")
+    result = cmd.run("tox", "-v")
     assert not result.ret
     result.stdout.fnmatch_lines([
         "*junit-python.xml*",
         "*1 passed*",
     ])
+    assert "sdist-make" not in result.stdout.str()
     result = cmd.run("tox", "-epython", )
     assert not result.ret
     result.stdout.fnmatch_lines([

diff -r 6a52c1c93e083f760e46f24219a91ba9f69b926f -r 
ddda508fcee1c7f91d465b5420a25b6b2b9554ef tox/_cmdline.py
--- a/tox/_cmdline.py
+++ b/tox/_cmdline.py
@@ -391,7 +391,7 @@
             return
         for venv in self.venvlist:
             if self.setupenv(venv):
-                if self.config.usedevelop:
+                if self.config.usedevelop or self.config.option.develop:
                     self.developpkg(venv, self.config.setupdir)
                 elif self.config.skipsdist:
                     self.finishvenv(venv)

diff -r 6a52c1c93e083f760e46f24219a91ba9f69b926f -r 
ddda508fcee1c7f91d465b5420a25b6b2b9554ef tox/_config.py
--- a/tox/_config.py
+++ b/tox/_config.py
@@ -90,6 +90,8 @@
         help="skip invoking test commands.")
     parser.add_argument("--sdistonly", action="store_true", dest="sdistonly",
         help="only perform the sdist packaging activity.")
+    parser.add_argument("--develop", action="store_true", dest="develop",
+        help="install package in the venv using setup.py develop")
     parser.add_argument("--installpkg", action="store", default=None,
         help="use specified package for installation into venv")
     parser.add_argument('-i', action="append",
@@ -195,8 +197,9 @@
         config.toxworkdir = reader.getpath(toxsection, "toxworkdir",
                                            "{toxinidir}/.tox")
         config.usedevelop = reader.getbool(toxsection, "usedevelop", False)
-        config.skipsdist = reader.getbool(
-            toxsection, "skipsdist", config.usedevelop)
+        config.skipsdist = reader.getbool(toxsection, "skipsdist",
+                                          config.usedevelop
+                                          or config.option.develop)
         config.minversion = reader.getdefault(toxsection, "minversion", None)
 
         # determine indexserver dictionary


https://bitbucket.org/hpk42/tox/commits/dc7637581d8a/
Changeset:   dc7637581d8a
User:        mordred
Date:        2013-07-16 16:58:20
Summary:     Add documentation for the --develop option
Affected #:  1 file

diff -r ddda508fcee1c7f91d465b5420a25b6b2b9554ef -r 
dc7637581d8ad1a3793f9b894ffb0a8f758524ed doc/example/general.txt
--- a/doc/example/general.txt
+++ b/doc/example/general.txt
@@ -169,7 +169,8 @@
     [tox]
     usedevelop=True
 
-Which will set ``skipsdist`` to True and then perform the ``setup.py develop``
+And a corresponding command line option ``--develop``, which will set
+``skipsdist`` to True and then perform the ``setup.py develop``
 step at the place where ``tox`` normally perfoms the installation of the sdist.
 Specifically, it actually runs ``pip install -e .`` behind the scenes, which
 itself calls ``setup.py develop``.


https://bitbucket.org/hpk42/tox/commits/bfc4a27950dc/
Changeset:   bfc4a27950dc
User:        hpk42
Date:        2013-07-16 17:01:38
Summary:     Merged in mordred/configurable-hooks (pull request #49)

Make software installation more configurable
Affected #:  6 files

diff -r 2567d6b26c8995df6cacee337d90f34418057293 -r 
bfc4a27950dce50e8d49ede674ca73fdaecdf981 doc/config.txt
--- a/doc/config.txt
+++ b/doc/config.txt
@@ -21,6 +21,8 @@
     distdir=path      # defaults to {toxworkdir}/dist
     distshare=path    # defaults to {homedir}/.tox/distshare
     envlist=ENVLIST   # defaults to the list of all environments
+    skipsdist=BOOL    # defaults to false
+    usedevelop=BOOL   # use python setup.py develop, defaults to false
 
 
 ``tox`` autodetects if it is running in a Jenkins_ context

diff -r 2567d6b26c8995df6cacee337d90f34418057293 -r 
bfc4a27950dce50e8d49ede674ca73fdaecdf981 doc/example/general.txt
--- a/doc/example/general.txt
+++ b/doc/example/general.txt
@@ -144,4 +144,38 @@
     [testenv:py27]
     basepython=/my/path/to/python2.7
 
+Avoiding expensive sdist
+------------------------
+
+Some projects are large enough that running and sdist, followed by
+an install everytime can be prohibitively costly. To solve this,
+there are two different options you can add to the ``tox`` section. First,
+you can simply ask tox to please not make an sdist::
+
+    [tox]
+    skipsdist=True
+
+If you do this, your local software package will not be installed into
+the virtualenv. You should probably be ok with that, or take steps
+to deal with it in your commands section::
+
+    [testenv]
+    commands =
+        python setup.py develop
+        py.test
+
+Running setup.py develop is a common enough model that it has its own option::
+
+    [tox]
+    usedevelop=True
+
+And a corresponding command line option ``--develop``, which will set
+``skipsdist`` to True and then perform the ``setup.py develop``
+step at the place where ``tox`` normally perfoms the installation of the sdist.
+Specifically, it actually runs ``pip install -e .`` behind the scenes, which
+itself calls ``setup.py develop``.
+
+There is an optimization coded in to not bother re-running the command if
+``$projectname.egg-info`` is newer than ``setup.py`` or ``setup.cfg``.
+
 .. include:: ../links.txt

diff -r 2567d6b26c8995df6cacee337d90f34418057293 -r 
bfc4a27950dce50e8d49ede674ca73fdaecdf981 tests/test_z_cmdline.py
--- a/tests/test_z_cmdline.py
+++ b/tests/test_z_cmdline.py
@@ -252,6 +252,23 @@
         "*ERROR*unknown*environment*qpwoei*",
     ])
 
+def test_skip_sdist(cmd, initproj):
+    initproj("pkg123-0.7", filedefs={
+        'tests': {'test_hello.py': "def test_hello(): pass"},
+        'setup.py': """
+            syntax error
+        """
+        ,
+        'tox.ini': '''
+            [tox]
+            skipsdist=True
+            [testenv]
+            commands=echo done
+        '''
+    })
+    result = cmd.run("tox", )
+    assert result.ret == 0
+
 def test_sdist_fails(cmd, initproj):
     initproj("pkg123-0.7", filedefs={
         'tests': {'test_hello.py': "def test_hello(): pass"},
@@ -342,6 +359,67 @@
     ])
 
 
+def test_develop(initproj, cmd):
+    initproj("example123", filedefs={'tox.ini': """
+    """})
+    result = cmd.run("tox", "-v", "--develop")
+    assert not result.ret
+    assert "sdist-make" not in result.stdout.str()
+
+def test_test_usedevelop(cmd, initproj):
+    initproj("example123-0.5", filedefs={
+        'tests': {'test_hello.py': """
+            def test_hello(pytestconfig):
+                pass
+            """,
+        },
+        'tox.ini': '''
+            [tox]
+            usedevelop=True
+            [testenv]
+            changedir=tests
+            commands=
+                py.test --basetemp={envtmpdir} --junitxml=junit-{envname}.xml 
[]
+            deps=pytest
+        '''
+    })
+    result = cmd.run("tox", "-v")
+    assert not result.ret
+    result.stdout.fnmatch_lines([
+        "*junit-python.xml*",
+        "*1 passed*",
+    ])
+    assert "sdist-make" not in result.stdout.str()
+    result = cmd.run("tox", "-epython", )
+    assert not result.ret
+    result.stdout.fnmatch_lines([
+        "*1 passed*",
+        "*summary*",
+        "*python: commands succeeded"
+    ])
+    # see that things work with a different CWD
+    old = cmd.tmpdir.chdir()
+    result = cmd.run("tox", "-c", "example123/tox.ini")
+    assert not result.ret
+    result.stdout.fnmatch_lines([
+        "*1 passed*",
+        "*summary*",
+        "*python: commands succeeded"
+    ])
+    old.chdir()
+    # see that tests can also fail and retcode is correct
+    testfile = py.path.local("tests").join("test_hello.py")
+    assert testfile.check()
+    testfile.write("def test_fail(): assert 0")
+    result = cmd.run("tox", )
+    assert result.ret
+    result.stdout.fnmatch_lines([
+        "*1 failed*",
+        "*summary*",
+        "*python: *failed*",
+    ])
+
+
 def test_test_piphelp(initproj, cmd):
     initproj("example123", filedefs={'tox.ini': """
         # content of: tox.ini

diff -r 2567d6b26c8995df6cacee337d90f34418057293 -r 
bfc4a27950dce50e8d49ede674ca73fdaecdf981 tox/_cmdline.py
--- a/tox/_cmdline.py
+++ b/tox/_cmdline.py
@@ -73,7 +73,7 @@
         f.flush()
         return f
 
-    def popen(self, args, cwd=None, env=None, redirect=True):
+    def popen(self, args, cwd=None, env=None, redirect=True, returnout=False):
         logged_command = "%s$ %s" %(cwd, " ".join(map(str, args)))
         f = outpath = None
         if redirect:
@@ -82,6 +82,8 @@
                     self.id, self.msg, args, env))
             f.flush()
             self.popen_outpath = outpath = py.path.local(f.name)
+        elif returnout:
+            f = subprocess.PIPE
         if cwd is None:
             # XXX cwd = self.session.config.cwd
             cwd = py.path.local()
@@ -327,6 +329,22 @@
                 return False
             return True
 
+    def finishvenv(self, venv):
+        action = self.newaction(venv, "finishvenv")
+        with action:
+            venv.finish()
+            return True
+
+    def developpkg(self, venv, setupdir):
+        action = self.newaction(venv, "developpkg", setupdir)
+        with action:
+            try:
+                venv.developpkg(setupdir, action)
+                return True
+            except tox.exception.InvocationError:
+                venv.status = sys.exc_info()[1]
+                return False
+
     def installpkg(self, venv, sdist_path):
         action = self.newaction(venv, "installpkg", sdist_path)
         with action:
@@ -362,19 +380,28 @@
         return sdist_path
 
     def subcommand_test(self):
-        sdist_path = self.sdist()
-        if not sdist_path:
-            return 2
+        if self.config.skipsdist:
+            self.report.info("skipping sdist step")
+            sdist_path = None
+        else:
+            sdist_path = self.sdist()
+            if not sdist_path:
+                return 2
         if self.config.option.sdistonly:
             return
         for venv in self.venvlist:
             if self.setupenv(venv):
-                self.installpkg(venv, sdist_path)
-                self.runtestenv(venv, sdist_path)
+                if self.config.usedevelop or self.config.option.develop:
+                    self.developpkg(venv, self.config.setupdir)
+                elif self.config.skipsdist:
+                    self.finishvenv(venv)
+                else:
+                    self.installpkg(venv, sdist_path)
+                self.runtestenv(venv)
         retcode = self._summary()
         return retcode
 
-    def runtestenv(self, venv, sdist_path, redirect=False):
+    def runtestenv(self, venv, redirect=False):
         if not self.config.option.notest:
             if venv.status:
                 return
@@ -408,6 +435,8 @@
         self.report.keyvalue("toxworkdir: ", self.config.toxworkdir)
         self.report.keyvalue("setupdir:   ", self.config.setupdir)
         self.report.keyvalue("distshare:  ", self.config.distshare)
+        self.report.keyvalue("skipsdist:  ", self.config.skipsdist)
+        self.report.keyvalue("usedevelop: ", self.config.usedevelop)
         self.report.tw.line()
         for envconfig in self.config.envconfigs.values():
             self.report.line("[testenv:%s]" % envconfig.envname, bold=True)

diff -r 2567d6b26c8995df6cacee337d90f34418057293 -r 
bfc4a27950dce50e8d49ede674ca73fdaecdf981 tox/_config.py
--- a/tox/_config.py
+++ b/tox/_config.py
@@ -90,6 +90,8 @@
         help="skip invoking test commands.")
     parser.add_argument("--sdistonly", action="store_true", dest="sdistonly",
         help="only perform the sdist packaging activity.")
+    parser.add_argument("--develop", action="store_true", dest="develop",
+        help="install package in the venv using setup.py develop")
     parser.add_argument("--installpkg", action="store", default=None,
         help="use specified package for installation into venv")
     parser.add_argument('-i', action="append",
@@ -194,6 +196,10 @@
                               homedir=config.homedir)
         config.toxworkdir = reader.getpath(toxsection, "toxworkdir",
                                            "{toxinidir}/.tox")
+        config.usedevelop = reader.getbool(toxsection, "usedevelop", False)
+        config.skipsdist = reader.getbool(toxsection, "skipsdist",
+                                          config.usedevelop
+                                          or config.option.develop)
         config.minversion = reader.getdefault(toxsection, "minversion", None)
 
         # determine indexserver dictionary

diff -r 2567d6b26c8995df6cacee337d90f34418057293 -r 
bfc4a27950dce50e8d49ede674ca73fdaecdf981 tox/_venv.py
--- a/tox/_venv.py
+++ b/tox/_venv.py
@@ -197,11 +197,36 @@
         self._pcall(args, venv=False, action=action, cwd=basepath)
         self.just_created = True
 
+    def finish(self):
+        self._getliveconfig().writeconfig(self.path_config)
+
+    def _needs_reinstall(self, setupdir, action):
+        setup_py = setupdir.join('setup.py')
+        setup_cfg = setupdir.join('setup.cfg')
+        args = [str(self.getconfigexecutable()), str(setup_py), '--name']
+        output = action.popen(args, cwd=setupdir, redirect=False,
+                              returnout=True)
+        name = output.strip().decode('utf-8')
+        egg_info = setupdir.join('.'.join((name, 'egg-info')))
+        for conf_file in (setup_py, setup_cfg):
+            if (not egg_info.check() or (conf_file.check()
+                    and conf_file.mtime() > egg_info.mtime())):
+                return True
+        return False
+
+    def developpkg(self, setupdir, action):
+        assert action is not None
+        self.finish()
+        if not self._needs_reinstall(setupdir, action):
+            return
+        extraopts = ['--no-deps']
+        self._install(['-e', setupdir], extraopts=extraopts, action=action)
+
     def installpkg(self, sdistpath, action):
         assert action is not None
         if getattr(self, 'just_created', False):
             action.setactivity("inst", sdistpath)
-            self._getliveconfig().writeconfig(self.path_config)
+            self.finish()
             extraopts = []
         else:
             action.setactivity("inst-nodeps", sdistpath)

Repository URL: https://bitbucket.org/hpk42/tox/

--

This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
_______________________________________________
pytest-commit mailing list
pytest-commit@python.org
http://mail.python.org/mailman/listinfo/pytest-commit

Reply via email to