Repository: tox-dev/tox-travis

Issue:
Respect specified tox configuration file
`tox -c CONFIGFILE` tells tox exactly where to find the Tox configuration file. This defaults to `tox.ini`. If this option is given, Tox-Travis should look for its configuration in that file as well.

References #56.

Discussion:
codecov-io: # [Codecov](https://codecov.io/gh/tox-dev/tox-travis/pull/59?src=pr&el=h1) Report
> Merging [#59](https://codecov.io/gh/tox-dev/tox-travis/pull/59?src=pr&el=desc) into [master](https://codecov.io/gh/tox-dev/tox-travis/commit/e83cadff47ca060bb437a4a12311a9a6b407ebcb?src=pr&el=desc) will **decrease** coverage by `1.96%`.
> The diff coverage is `65.85%`.

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

```diff
@@            Coverage Diff            @@
##           master     #59      +/-   ##
=========================================
- Coverage   75.26%   73.3%   -1.97%     
=========================================
  Files           5       4       -1     
  Lines         186     206      +20     
  Branches       45      51       +6     
=========================================
+ Hits          140     151      +11     
- Misses         39      43       +4     
- Partials        7      12       +5
```


| [Impacted Files](https://codecov.io/gh/tox-dev/tox-travis/pull/59?src=pr&el=tree) | Coverage Δ | |
|---|---|---|
| [src/tox\_travis/toxenv.py](https://codecov.io/gh/tox-dev/tox-travis/pull/59?src=pr&el=tree#diff-c3JjL3RveF90cmF2aXMvdG94ZW52LnB5) | `89.87% <100%> (-4.58%)` | :arrow_down: |
| [src/tox\_travis/after.py](https://codecov.io/gh/tox-dev/tox-travis/pull/59?src=pr&el=tree#diff-c3JjL3RveF90cmF2aXMvYWZ0ZXIucHk=) | `59.77% <50%> (+2.12%)` | :arrow_up: |
| [src/tox\_travis/utils.py](https://codecov.io/gh/tox-dev/tox-travis/pull/59?src=pr&el=tree#diff-c3JjL3RveF90cmF2aXMvdXRpbHMucHk=) | `65.38% <57.14%> (-34.62%)` | :arrow_down: |
| [src/tox\_travis/hooks.py](https://codecov.io/gh/tox-dev/tox-travis/pull/59?src=pr&el=tree#diff-c3JjL3RveF90cmF2aXMvaG9va3MucHk=) | `78.57% <75%> (-8.1%)` | :arrow_down: |
| [src/tox\_travis/hacks.py](https://codecov.io/gh/tox-dev/tox-travis/pull/59?src=pr&el=tree#diff-c3JjL3RveF90cmF2aXMvaGFja3MucHk=) | | |

------

[Continue to review full report at Codecov](https://codecov.io/gh/tox-dev/tox-travis/pull/59?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-travis/pull/59?src=pr&el=footer). Last update [e83cadf...df2fed4](https://codecov.io/gh/tox-dev/tox-travis/pull/59?src=pr&el=lastupdated). Read the [comment docs](https://docs.codecov.io/docs/pull-request-comments).

ryanhiebert: This is ready for review. I've added a test, and rebased it to be based on us now using the tox_configure hook. So it's just using the config that Tox loaded, instead of loading our own.
ryanhiebert: >>> I'm going to clean this up and merge it.
>>
>> Tests?
>
> Yes, those too. I spoke like I wasn't going to, but I definitely do, and hopefully a green review too ;-)

Confession: I totally wanted to skip writing tests. My excuse was that it was a bug fix and I wanted to get it fixed quickly. In hindsight the original pull request was certainly too big to skip tests, and I'm really thankful to @rpkilby for calling me out on it with a single word. I apologize for obfuscating my true intentions at the time.

At this point the patch is much smaller, and has added a regression test. In an effort to maintain my own momentum, I may merge some PRs that I perceive to be less challenging, like this one now is, though I intend to give @rpkilby a couple days before I do that with this particular pull request. Or anyone else that's willing. I sometimes take @rpkilby for granted because of how absolutely awesome he's been as a maintainer.

Patch:
diff --git a/src/tox_travis/after.py b/src/tox_travis/after.py
index 9f25f20..caf3750 100644
--- a/src/tox_travis/after.py
+++ b/src/tox_travis/after.py
@@ -4,7 +4,6 @@ import os
 import sys
 import json
 import time
-import py
 
 from tox.config import _split_env as split_env
 try:
@@ -32,18 +31,18 @@ def travis_after_monkeypatch():
         retcode = real_subcommand_test(self)
         if retcode == 0 and self.config.option.travis_after:
             # No need to run if the tests failed anyway
-            travis_after(self.config.envlist)
+            travis_after(self.config.envlist, self.config._cfg)
         return retcode
     tox.session.Session.subcommand_test = subcommand_test
 
 
-def travis_after(envlist):
+def travis_after(envlist, ini):
     """Wait for all jobs to finish, then exit successfully."""
     # after-all disabled for pull requests
     if os.environ.get('TRAVIS_PULL_REQUEST', 'false') != 'false':
         return
 
-    if not after_config_matches(envlist):
+    if not after_config_matches(envlist, ini):
         return  # This is not the one that needs to wait
 
     github_token = os.environ.get('GITHUB_TOKEN')
@@ -77,10 +76,9 @@ def travis_after(envlist):
     print('All required jobs were successful.')
 
 
-def after_config_matches(envlist):
+def after_config_matches(envlist, ini):
     """Determine if this job should wait for the others."""
-    config = py.iniconfig.IniConfig('tox.ini')
-    section = config.sections.get('travis:after', {})
+    section = ini.sections.get('travis:after', {})
 
     if not section:
         return False  # Never wait if it's not configured
diff --git a/src/tox_travis/toxenv.py b/src/tox_travis/toxenv.py
index 631f45b..8bed3c7 100644
--- a/src/tox_travis/toxenv.py
+++ b/src/tox_travis/toxenv.py
@@ -4,7 +4,6 @@ from itertools import product
 import os
 import sys
 import re
-import py
 import tox.config
 from tox.config import _split_env as split_env
 from .utils import TRAVIS_FACTORS, parse_dict
@@ -15,7 +14,7 @@ def default_toxenv(config):
     if 'TOXENV' in os.environ or config.option.env:
         return  # Skip any processing if already set
 
-    ini = py.iniconfig.IniConfig('tox.ini')
+    ini = config._cfg
 
     # Find the envs that tox knows about
     declared_envs = get_declared_envs(ini)
@@ -235,8 +234,7 @@ def env_matches(declared, desired):
 
 def override_ignore_outcome(config):
     """Override ignore_outcome if unignore_outcomes is set to True."""
-    tox_config = py.iniconfig.IniConfig('tox.ini')
-    travis_reader = tox.config.SectionReader("travis", tox_config)
+    travis_reader = tox.config.SectionReader("travis", config._cfg)
     if travis_reader.getbool('unignore_outcomes', False):
         for envconfig in config.envconfigs.values():
             envconfig.ignore_outcome = False


Test patch:
diff --git a/tests/test_after.py b/tests/test_after.py
index da63063..06fb01c 100644
--- a/tests/test_after.py
+++ b/tests/test_after.py
@@ -13,7 +13,7 @@ class TestAfter:
         monkeypatch.setenv('TRAVIS', 'true')
         monkeypatch.setenv('TRAVIS_PULL_REQUEST', '1')
 
-        travis_after(mocker.Mock())
+        travis_after(mocker.Mock(), mocker.Mock())
 
         out, err = capsys.readouterr()
         assert out == ''
@@ -25,7 +25,7 @@ class TestAfter:
                      return_value=True)
         monkeypatch.setenv('TRAVIS', 'true')
         with pytest.raises(SystemExit) as excinfo:
-            travis_after(mocker.Mock())
+            travis_after(mocker.Mock(), mocker.Mock())
 
         assert excinfo.value.code == 32
         out, err = capsys.readouterr()
@@ -38,7 +38,7 @@ class TestAfter:
         monkeypatch.setenv('TRAVIS', 'true')
         monkeypatch.setenv('GITHUB_TOKEN', 'spamandeggs')
         with pytest.raises(SystemExit) as excinfo:
-            travis_after(mocker.Mock())
+            travis_after(mocker.Mock(), mocker.Mock())
 
         assert excinfo.value.code == 34
         out, err = capsys.readouterr()
@@ -52,7 +52,7 @@ class TestAfter:
         monkeypatch.setenv('GITHUB_TOKEN', 'spamandeggs')
         monkeypatch.setenv('TRAVIS_BUILD_ID', '1234')
         with pytest.raises(SystemExit) as excinfo:
-            travis_after(mocker.Mock())
+            travis_after(mocker.Mock(), mocker.Mock())
 
         assert excinfo.value.code == 34
         out, err = capsys.readouterr()
@@ -69,7 +69,7 @@ class TestAfter:
         # TRAVIS_API_URL is set to a reasonable default
         monkeypatch.setenv('TRAVIS_API_URL', '')
         with pytest.raises(SystemExit) as excinfo:
-            travis_after(mocker.Mock())
+            travis_after(mocker.Mock(), mocker.Mock())
 
         assert excinfo.value.code == 34
         out, err = capsys.readouterr()
@@ -86,7 +86,7 @@ class TestAfter:
         # TRAVIS_POLLING_INTERVAL is set to a reasonable default
         monkeypatch.setenv('TRAVIS_POLLING_INTERVAL', 'xbe')
         with pytest.raises(SystemExit) as excinfo:
-            travis_after(mocker.Mock())
+            travis_after(mocker.Mock(), mocker.Mock())
 
         assert excinfo.value.code == 33
         out, err = capsys.readouterr()
@@ -186,7 +186,7 @@ class TestAfter:
         get_json.responses = iter(responses)
 
         mocker.patch('tox_travis.after.get_json', side_effect=get_json)
-        travis_after(mocker.Mock())
+        travis_after(mocker.Mock(), mocker.Mock())
         out, err = capsys.readouterr()
         assert 'All required jobs were successful.' in out
 
@@ -289,7 +289,7 @@ class TestAfter:
         mocker.patch('tox_travis.after.get_json', side_effect=get_json)
 
         with pytest.raises(SystemExit) as excinfo:
-            travis_after(mocker.Mock())
+            travis_after(mocker.Mock(), mocker.Mock())
 
         assert excinfo.value.code == 35
         out, err = capsys.readouterr()
diff --git a/tests/test_toxenv.py b/tests/test_toxenv.py
index bd62707..91daef9 100644
--- a/tests/test_toxenv.py
+++ b/tests/test_toxenv.py
@@ -119,27 +119,33 @@ unignore_outcomes = False
 class TestToxEnv:
     """Test the logic to automatically configure TOXENV with Travis."""
 
-    def tox_envs(self):
+    def tox_envs(self, **kwargs):
         """Find the envs that tox sees."""
-        returncode, stdout, stderr = self.tox_envs_raw()
+        returncode, stdout, stderr = self.tox_envs_raw(**kwargs)
         assert returncode == 0, stderr
         return [env for env in stdout.strip().split('\n')]
 
-    def tox_envs_raw(self):
+    def tox_envs_raw(self, ini_filename=None):
         """Return the raw output of finding what tox sees."""
-        return self.call_raw(['tox', '-l'])
+        command = ['tox', '-l']
+        if ini_filename is not None:
+            command += ['-c', ini_filename]
+        return self.call_raw(command)
 
-    def tox_config(self):
+    def tox_config(self, **kwargs):
         """Returns the configuration per configuration as computed by tox."""
-        returncode, stdout, stderr = self.tox_config_raw()
+        returncode, stdout, stderr = self.tox_config_raw(**kwargs)
         assert returncode == 0, stderr
         ini = "[global]\n" + re.sub(
             re.compile(r'^\s+', re.MULTILINE), '', stdout)
         return py.iniconfig.IniConfig('', data=ini)
 
-    def tox_config_raw(self):
+    def tox_config_raw(self, ini_filename=None):
         """Return the raw output of finding the complex tox env config."""
-        return self.call_raw(['tox', '--showconfig'])
+        command = ['tox', '--showconfig']
+        if ini_filename is not None:
+            command += ['-c', ini_filename]
+        return self.call_raw(command)
 
     def call_raw(self, command):
         """Return the raw output of the given command."""
@@ -152,10 +158,11 @@ class TestToxEnv:
     def configure(self, tmpdir, monkeypatch, tox_ini,
                   version=None, major=None, minor=None,
                   travis_version=None, travis_os=None,
-                  travis_language=None, env=None):
+                  travis_language=None, env=None,
+                  ini_filename='tox.ini'):
         """Configure the environment for running a test."""
         origdir = tmpdir.chdir()
-        tmpdir.join('tox.ini').write(tox_ini)
+        tmpdir.join(ini_filename).write(tox_ini)
         tmpdir.join('.coveragerc').write(coverage_config)
 
         if version or travis_version or travis_os or travis_language:
@@ -202,6 +209,12 @@ class TestToxEnv:
             ]
             assert self.tox_envs() == expected
 
+    def test_travis_config_filename(self, tmpdir, monkeypatch):
+        """Give the correct env for CPython 2.7."""
+        with self.configure(tmpdir, monkeypatch, tox_ini, 'CPython', 3, 6,
+                            ini_filename='spam.ini'):
+            assert self.tox_envs(ini_filename='spam.ini') == ['py36']
+
     def test_travis_default_26(self, tmpdir, monkeypatch):
         """Give the correct env for CPython 2.6."""
         with self.configure(tmpdir, monkeypatch, tox_ini, 'CPython', 2, 6):