Repository: tox-dev/tox
Pull request #673 (2017-11-18 00:14:21)

Do not print empty headings
Headings like installed: <packages> will not be printed if there is no output to display after the :, unless verbosity is set.

Fixes issue #601.


codecov[bot]: # [Codecov](https://codecov.io/gh/tox-dev/tox/pull/673?src=pr&el=h1) Report
> Merging [#673](https://codecov.io/gh/tox-dev/tox/pull/673?src=pr&el=desc) into [master](https://codecov.io/gh/tox-dev/tox/commit/aa71b8ebfdfcb40304e3844da39a32b6fc4f63c3?src=pr&el=desc) will **decrease** coverage by `1.26%`.
> The diff coverage is `100%`.

[![Impacted file tree graph](https://codecov.io/gh/tox-dev/tox/pull/673/graphs/tree.svg?src=pr&token=DYodAwDCZ5&width=650&height=150)](https://codecov.io/gh/tox-dev/tox/pull/673?src=pr&el=tree)

```diff
@@            Coverage Diff             @@
##           master     #673      +/-   ##
==========================================
- Coverage   90.73%   89.46%   -1.27%     
==========================================
  Files          11       10       -1     
  Lines        2363     2364       +1     
  Branches      395      396       +1     
==========================================
- Hits         2144     2115      -29     
- Misses        144      174      +30     
  Partials       75       75
```


| [Impacted Files](https://codecov.io/gh/tox-dev/tox/pull/673?src=pr&el=tree) | Coverage Δ | |
|---|---|---|
| [tox/session.py](https://codecov.io/gh/tox-dev/tox/pull/673?src=pr&el=tree#diff-dG94L3Nlc3Npb24ucHk=) | `91.63% <100%> (-0.34%)` | :arrow_down: |
| [tox/interpreters.py](https://codecov.io/gh/tox-dev/tox/pull/673?src=pr&el=tree#diff-dG94L2ludGVycHJldGVycy5weQ==) | `59.37% <0%> (-17.97%)` | :arrow_down: |
| [tox/venv.py](https://codecov.io/gh/tox-dev/tox/pull/673?src=pr&el=tree#diff-dG94L3ZlbnYucHk=) | `92.52% <0%> (-1.25%)` | :arrow_down: |
| [tox/config.py](https://codecov.io/gh/tox-dev/tox/pull/673?src=pr&el=tree#diff-dG94L2NvbmZpZy5weQ==) | `94.77% <0%> (-0.26%)` | :arrow_down: |
| [tox/\_\_main\_\_.py](https://codecov.io/gh/tox-dev/tox/pull/673?src=pr&el=tree#diff-dG94L19fbWFpbl9fLnB5) | | |

------

[Continue to review full report at Codecov](https://codecov.io/gh/tox-dev/tox/pull/673?src=pr&el=continue).
> **Legend** - [Click here to learn more](https://docs.codecov.io/docs/codecov-delta)
> `Δ = absolute <relative> (impact)`, `ø = not affected`, `? = missing data`
> Powered by [Codecov](https://codecov.io/gh/tox-dev/tox/pull/673?src=pr&el=footer). Last update [aa71b8e...3887ed6](https://codecov.io/gh/tox-dev/tox/pull/673?src=pr&el=lastupdated). Read the [comment docs](https://docs.codecov.io/docs/pull-request-comments).

cryvate: Travis failed due to #656. All environments bar 3.4 passed.

Patch:
diff --git a/.travis.yml b/.travis.yml
index 0b7da097..4910ea00 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -23,7 +23,7 @@ matrix:
     language: generic
 
 before_install: if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then source .travis-osx; fi
-install: pip install --pre -U tox
+install: pip install six && pip install --pre -U tox
 script: tox -e py
 after_success:
   - tox -e coverage
diff --git a/CONTRIBUTORS b/CONTRIBUTORS
index 8a4b8244..c7592b45 100644
--- a/CONTRIBUTORS
+++ b/CONTRIBUTORS
@@ -21,7 +21,6 @@ Fernando L. Pereira
 Henk-Jaap Wagenaar
 Igor Duarte Cardoso
 Ionel Maries Cristian
-Ionel Maries Cristian
 Itxaka Serrano
 Jannis Leidel
 Johannes Christ
diff --git a/changelog/601.feature.rst b/changelog/601.feature.rst
new file mode 100644
index 00000000..e189c3d3
--- /dev/null
+++ b/changelog/601.feature.rst
@@ -0,0 +1,1 @@
+Headings like ``installed: <packages>`` will not be printed if there is no output to display after the :, unless verbosity is set. By @cryvate
diff --git a/changelog/668.feature.rst b/changelog/668.feature.rst
new file mode 100644
index 00000000..5493845c
--- /dev/null
+++ b/changelog/668.feature.rst
@@ -0,0 +1,1 @@
+Allow spaces in command line options to pip in deps. Where previously only ``deps=-rreq.txt`` and ``deps=--requirement=req.txt`` worked, now also ``deps=-r req.txt`` and ``deps=--requirement req.txt`` work - by @cryvate
diff --git a/tox/config.py b/tox/config.py
index f4620f6d..b056431b 100755
--- a/tox/config.py
+++ b/tox/config.py
@@ -31,6 +31,18 @@ hookimpl = pluggy.HookimplMarker("tox")
 
 _dummy = object()
 
+PIP_INSTALL_SHORT_OPTIONS_ARGUMENT = ['-{0}'.format(option) for option in [
+    'c', 'e', 'r', 'b', 't', 'd',
+]]
+
+PIP_INSTALL_LONG_OPTIONS_ARGUMENT = ['--{0}'.format(option) for option in [
+    'constraint', 'editable', 'requirement', 'build', 'target', 'download',
+    'src', 'upgrade-strategy', 'install-options', 'global-option',
+    'root', 'prefix', 'no-binary', 'only-binary', 'index-url',
+    'extra-index-url', 'find-links', 'proxy', 'retries', 'timeout',
+    'exists-action', 'trusted-host', 'client-cert', 'cache-dir',
+]]
+
 
 def get_plugin_manager(plugins=()):
     # initialize plugin manager
@@ -124,6 +136,24 @@ class DepOption:
             else:
                 name = depline.strip()
                 ixserver = None
+
+                # we need to process options, in case they contain a space,
+                # as the subprocess call to pip install will otherwise fail.
+
+                # in case of a short option, we remove the space
+                for option in PIP_INSTALL_SHORT_OPTIONS_ARGUMENT:
+                    if name.startswith(option):
+                        name = '{0}{1}'.format(
+                            option, name[len(option):].strip()
+                        )
+
+                # in case of a long option, we add an equal sign
+                for option in PIP_INSTALL_LONG_OPTIONS_ARGUMENT:
+                    if name.startswith(option + ' '):
+                        name = '{0}={1}'.format(
+                            option, name[len(option):].strip()
+                        )
+
             name = self._replace_forced_dep(name, config)
             deps.append(DepConfig(name, ixserver))
         return deps
diff --git a/tox/session.py b/tox/session.py
index b2aeec6a..f61b5044 100644
--- a/tox/session.py
+++ b/tox/session.py
@@ -98,7 +98,10 @@ class Action(object):
 
     def setactivity(self, name, msg):
         self.activity = name
-        self.report.verbosity0("%s %s: %s" % (self.venvname, name, msg), bold=True)
+        if msg:
+            self.report.verbosity0("%s %s: %s" % (self.venvname, name, msg), bold=True)
+        else:
+            self.report.verbosity1("%s %s: %s" % (self.venvname, name, msg), bold=True)
 
     def info(self, name, msg):
         self.report.verbosity1("%s %s: %s" % (self.venvname, name, msg), bold=True)


Test patch:
diff --git a/tests/test_config.py b/tests/test_config.py
index 430daf30..30da4f04 100644
--- a/tests/test_config.py
+++ b/tests/test_config.py
@@ -118,6 +118,23 @@ class TestVenvConfig:
             'dep1==1.5', 'https://pypi.python.org/xyz/pkg1.tar.gz'
         ]
 
+    def test_process_deps(self, newconfig):
+        config = newconfig([], """
+            [testenv]
+            deps =
+                -r requirements.txt
+                --index-url https://pypi.org/simple
+                -fhttps://pypi.org/packages
+                --global-option=foo
+                -v dep1
+                --help dep2
+        """)  # note that those last two are invalid
+        assert [str(x) for x in config.envconfigs['python'].deps] == [
+            '-rrequirements.txt', '--index-url=https://pypi.org/simple',
+            '-fhttps://pypi.org/packages', '--global-option=foo',
+            '-v dep1', '--help dep2'
+        ]
+
     def test_is_same_dep(self):
         """
         Ensure correct parseini._is_same_dep is working with a few samples.
diff --git a/tests/test_z_cmdline.py b/tests/test_z_cmdline.py
index 91122456..406a20aa 100644
--- a/tests/test_z_cmdline.py
+++ b/tests/test_z_cmdline.py
@@ -689,6 +689,28 @@ def test_alwayscopy_default(initproj, cmd):
     assert "virtualenv --always-copy" not in result.stdout.str()
 
 
+def test_empty_activity_ignored(initproj, cmd):
+    initproj("example123", filedefs={'tox.ini': """
+            [testenv]
+            list_dependencies_command=echo
+            commands={envpython} --version
+    """})
+    result = cmd.run("tox")
+    assert not result.ret
+    assert "installed:" not in result.stdout.str()
+
+
+def test_empty_activity_shown_verbose(initproj, cmd):
+    initproj("example123", filedefs={'tox.ini': """
+            [testenv]
+            list_dependencies_command=echo
+            commands={envpython} --version
+    """})
+    result = cmd.run("tox", "-v")
+    assert not result.ret
+    assert "installed:" in result.stdout.str()
+
+
 def test_test_piphelp(initproj, cmd):
     initproj("example123", filedefs={'tox.ini': """
         # content of: tox.ini