From c1e99112eede07f6f95d482f9eef388ea1ba459b Mon Sep 17 00:00:00 2001 From: Dan Ring Date: Thu, 17 Dec 2015 15:44:22 -0500 Subject: Add --workdir to override the 'toxworkdir' config option --- tox/config.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'tox') diff --git a/tox/config.py b/tox/config.py index 079dff3..e071805 100644 --- a/tox/config.py +++ b/tox/config.py @@ -366,6 +366,9 @@ def tox_addoption(parser): help="override sitepackages setting to True in all envs") parser.add_argument("--skip-missing-interpreters", action="store_true", help="don't fail tests for missing interpreters") + parser.add_argument("--workdir", action="store", + dest="workdir", metavar="PATH", default=None, + help="tox working directory") parser.add_argument("args", nargs="*", help="additional arguments available to command positional substitution") @@ -664,7 +667,10 @@ class parseini: reader.addsubstitutions(toxinidir=config.toxinidir, homedir=config.homedir) - config.toxworkdir = reader.getpath("toxworkdir", "{toxinidir}/.tox") + if config.option.workdir is None: + config.toxworkdir = reader.getpath("toxworkdir", "{toxinidir}/.tox") + else: + config.toxworkdir = config.toxinidir.join(config.option.workdir, abs=True) config.minversion = reader.getstring("minversion", None) if not config.option.skip_missing_interpreters: -- cgit v1.2.1 From b9e5e7fe4f721a1705b02fc16e891a451ac298a2 Mon Sep 17 00:00:00 2001 From: Piet Delport Date: Mon, 4 Jan 2016 15:58:50 +0200 Subject: Mark guarded "unicode" reference with noqa --- tox/_quickstart.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'tox') diff --git a/tox/_quickstart.py b/tox/_quickstart.py index a397cb1..59ee48e 100644 --- a/tox/_quickstart.py +++ b/tox/_quickstart.py @@ -119,7 +119,7 @@ def do_prompt(d, key, text, default=None, validator=nonempty): x = term_input(prompt) if default and not x: x = default - if sys.version_info < (3, ) and not isinstance(x, unicode): + if sys.version_info < (3, ) and not isinstance(x, unicode): # noqa # 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: -- cgit v1.2.1 From b5ded7a6bc0e7407c08813faa95b66a624d60f52 Mon Sep 17 00:00:00 2001 From: Piet Delport Date: Mon, 4 Jan 2016 16:09:18 +0200 Subject: Remove separating spaces in "print (...)" (pep8 E211) --- tox/_pytestplugin.py | 6 +++--- tox/interpreters.py | 6 +++--- tox/result.py | 6 +++--- 3 files changed, 9 insertions(+), 9 deletions(-) (limited to 'tox') diff --git a/tox/_pytestplugin.py b/tox/_pytestplugin.py index f15d2ec..b7693fc 100644 --- a/tox/_pytestplugin.py +++ b/tox/_pytestplugin.py @@ -68,12 +68,12 @@ class ReportExpectMock: def generic_report(*args, **kwargs): self._calls.append((name,) + args) - print ("%s" % (self._calls[-1], )) + 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], )) + print("%s" % (self._calls[-1], )) return Action(self.session, venv, msg, args) def getnext(self, cat): @@ -316,7 +316,7 @@ def initproj(request, tmpdir): for p in base.visit(lambda x: x.check(file=1)): manifestlines.append("include %s" % p.relto(base)) create_files(base, {"MANIFEST.in": "\n".join(manifestlines)}) - print ("created project in %s" % (base,)) + print("created project in %s" % (base,)) base.chdir() return initproj diff --git a/tox/interpreters.py b/tox/interpreters.py index 66e6409..e049f1d 100644 --- a/tox/interpreters.py +++ b/tox/interpreters.py @@ -43,10 +43,10 @@ class Interpreters: try: res = exec_on_interpreter(info.executable, [inspect.getsource(sitepackagesdir), - "print (sitepackagesdir(%r))" % envdir]) + "print(sitepackagesdir(%r))" % envdir]) except ExecFailed: val = sys.exc_info()[1] - print ("execution failed: %s -- %s" % (val.out, val.err)) + print("execution failed: %s -- %s" % (val.out, val.err)) return "" else: return res["dir"] @@ -56,7 +56,7 @@ def run_and_get_interpreter_info(name, executable): assert executable try: result = exec_on_interpreter(executable, - [inspect.getsource(pyinfo), "print (pyinfo())"]) + [inspect.getsource(pyinfo), "print(pyinfo())"]) except ExecFailed: val = sys.exc_info()[1] return NoInterpreterInfo(name, executable=val.executable, diff --git a/tox/result.py b/tox/result.py index 96ac612..bad8cc3 100644 --- a/tox/result.py +++ b/tox/result.py @@ -47,9 +47,9 @@ class EnvLog: pythonexecutable = py.path.local(pythonexecutable) out = pythonexecutable.sysexec("-c", "import sys; " - "print (sys.executable);" - "print (list(sys.version_info)); " - "print (sys.version)") + "print(sys.executable);" + "print(list(sys.version_info)); " + "print(sys.version)") lines = out.splitlines() executable = lines.pop(0) version_info = eval(lines.pop(0)) -- cgit v1.2.1 From fc35dcd7521317f04f491f8135faea75f433e896 Mon Sep 17 00:00:00 2001 From: Nyiro Gergo Date: Thu, 14 Jan 2016 11:25:11 +0100 Subject: session.Reporter: delete _starttime at exit The __enter__ of with statement extend the action object with _starttime and assert if it had been already extended. Therefore the __exit__ should remove the extra attribute of the action. --- tox/session.py | 1 + 1 file changed, 1 insertion(+) (limited to 'tox') diff --git a/tox/session.py b/tox/session.py index ffb52d6..f97b365 100644 --- a/tox/session.py +++ b/tox/session.py @@ -252,6 +252,7 @@ class Reporter(object): # self.cumulated_time += duration self.verbosity2("%s finish: %s after %.2f seconds" % ( action.venvname, action.msg, duration), bold=True) + delattr(action, '_starttime') def startsummary(self): self.tw.sep("_", "summary") -- cgit v1.2.1 From 26370885293487883eb60cbedcff76a0c6dc938e Mon Sep 17 00:00:00 2001 From: Sachi King Date: Mon, 29 Feb 2016 15:45:11 +1100 Subject: Process minversion before all else Reading the tox.ini config file and processing it is done as one task, yet processing the minversion is done much later, as such if there is a bug fix in a newer version or a change that makes the tox.ini file incompatable with older versions tox will bail with a stack trace instead of a "Your tox is too old" message. This moves the version check as early as it can possibly be done, the very first value read out of tox.ini is minversion and it is immedeiatly compared to tox.__version__. --- tox/__init__.py | 6 ++++++ tox/config.py | 13 ++++++++++++- tox/session.py | 28 +++++++++++++++------------- 3 files changed, 33 insertions(+), 14 deletions(-) (limited to 'tox') diff --git a/tox/__init__.py b/tox/__init__.py index c17341d..6991c90 100644 --- a/tox/__init__.py +++ b/tox/__init__.py @@ -23,5 +23,11 @@ class exception: """ a directory did not exist. """ class MissingDependency(Error): """ a dependency could not be found or determined. """ + class MinVersionError(Error): + """ the installed tox version is lower than requested minversion. """ + + def __init__(self, message): + self.message = message + super(exception.MinVersionError, self).__init__(message) from tox.session import main as cmdline # noqa diff --git a/tox/config.py b/tox/config.py index 67454bc..78d070a 100644 --- a/tox/config.py +++ b/tox/config.py @@ -12,6 +12,7 @@ import pluggy import tox.interpreters from tox import hookspecs +from tox._verlib import NormalizedVersion import py @@ -664,8 +665,18 @@ class parseini: reader.addsubstitutions(toxinidir=config.toxinidir, homedir=config.homedir) - config.toxworkdir = reader.getpath("toxworkdir", "{toxinidir}/.tox") + # As older versions of tox may have bugs or incompatabilities that + # prevent parsing of tox.ini this must be the first thing checked. config.minversion = reader.getstring("minversion", None) + # Parse our compatability immediately + if config.minversion: + minversion = NormalizedVersion(self.config.minversion) + toxversion = NormalizedVersion(tox.__version__) + if toxversion < minversion: + raise tox.exception.MinVersionError( + "tox version is %s, required is at least %s" % ( + toxversion, minversion)) + config.toxworkdir = reader.getpath("toxworkdir", "{toxinidir}/.tox") if not config.option.skip_missing_interpreters: config.option.skip_missing_interpreters = \ diff --git a/tox/session.py b/tox/session.py index 93ef5d8..2ff4182 100644 --- a/tox/session.py +++ b/tox/session.py @@ -40,6 +40,10 @@ def main(args=None): raise SystemExit(retcode) except KeyboardInterrupt: raise SystemExit(2) + except tox.exception.MinVersionError as e: + r = Reporter(None) + r.error(e.message) + raise SystemExit(1) def show_help(config): @@ -233,6 +237,12 @@ class Reporter(object): self._reportedlines = [] # self.cumulated_time = 0.0 + def _get_verbosity(self): + if self.session: + return self.session.config.option.verbosity + else: + return 2 + def logpopen(self, popen, env): """ log information about the action.popen() created process. """ cmd = " ".join(map(str, popen.args)) @@ -257,11 +267,11 @@ class Reporter(object): self.tw.sep("_", "summary") def info(self, msg): - if self.session.config.option.verbosity >= 2: + if self._get_verbosity() >= 2: self.logline(msg) def using(self, msg): - if self.session.config.option.verbosity >= 1: + if self._get_verbosity() >= 1: self.logline("using %s" % (msg,), bold=True) def keyboard_interrupt(self): @@ -297,15 +307,15 @@ class Reporter(object): self.tw.line("%s" % msg, **opts) def verbosity0(self, msg, **opts): - if self.session.config.option.verbosity >= 0: + if self._get_verbosity() >= 0: self.logline("%s" % msg, **opts) def verbosity1(self, msg, **opts): - if self.session.config.option.verbosity >= 1: + if self._get_verbosity() >= 1: self.logline("%s" % msg, **opts) def verbosity2(self, msg, **opts): - if self.session.config.option.verbosity >= 2: + if self._get_verbosity() >= 2: self.logline("%s" % msg, **opts) # def log(self, msg): @@ -359,14 +369,6 @@ class Session: def runcommand(self): self.report.using("tox-%s from %s" % (tox.__version__, tox.__file__)) - if self.config.minversion: - minversion = NormalizedVersion(self.config.minversion) - toxversion = NormalizedVersion(tox.__version__) - if toxversion < minversion: - self.report.error( - "tox version is %s, required is at least %s" % ( - toxversion, minversion)) - raise SystemExit(1) if self.config.option.showconfig: self.showconfig() elif self.config.option.listenvs: -- cgit v1.2.1 From f580e1a594f220b974abe0a2de85339f479c0542 Mon Sep 17 00:00:00 2001 From: Walter Scheper Date: Thu, 10 Mar 2016 21:43:49 -0500 Subject: Support configuration through setup.cfg When the usual search for a config file fails, try loading setup.cfg with a section prefix of tox. Modeled on coverage's use of setup.cfg as an alternative config file. --- tox/config.py | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) (limited to 'tox') diff --git a/tox/config.py b/tox/config.py index 67454bc..aaca0ca 100644 --- a/tox/config.py +++ b/tox/config.py @@ -224,7 +224,10 @@ def parseconfig(args=None, plugins=()): if inipath.check(): break else: - feedback("toxini file %r not found" % (basename), sysexit=True) + inipath = py.path.local().join('setup.cfg') + if not inipath.check(): + feedback("toxini file %r not found" % (basename), sysexit=True) + try: parseini(config, inipath) except tox.exception.InterpreterNotFound: @@ -644,12 +647,18 @@ class parseini: self._cfg = py.iniconfig.IniConfig(config.toxinipath) config._cfg = self._cfg self.config = config + + if inipath.basename == 'setup.cfg': + prefix = 'tox' + else: + prefix = None ctxname = getcontextname() if ctxname == "jenkins": - reader = SectionReader("tox:jenkins", self._cfg, fallbacksections=['tox']) + reader = SectionReader("tox:jenkins", self._cfg, prefix=prefix, + fallbacksections=['tox']) distshare_default = "{toxworkdir}/distshare" elif not ctxname: - reader = SectionReader("tox", self._cfg) + reader = SectionReader("tox", self._cfg, prefix=prefix) distshare_default = "{homedir}/.tox/distshare" else: raise ValueError("invalid context") @@ -853,8 +862,12 @@ is_section_substitution = re.compile("{\[[^{}\s]+\]\S+?}").match class SectionReader: - def __init__(self, section_name, cfgparser, fallbacksections=None, factors=()): - self.section_name = section_name + def __init__(self, section_name, cfgparser, fallbacksections=None, + factors=(), prefix=None): + if prefix is None: + self.section_name = section_name + else: + self.section_name = "%s:%s" % (prefix, section_name) self._cfg = cfgparser self.fallbacksections = fallbacksections or [] self.factors = factors -- cgit v1.2.1 From 6c44042ac2357850365c83e7f31be4d74dd2199f Mon Sep 17 00:00:00 2001 From: holger krekel Date: Mon, 20 Jun 2016 16:40:36 +0200 Subject: fix issue66 by introducing using default "python -m pip" and introducing list_dependencies_command. (Ted, Holger) --- tox/__init__.py | 2 +- tox/_pytestplugin.py | 3 +++ tox/config.py | 9 ++++++++- tox/session.py | 5 +++-- 4 files changed, 15 insertions(+), 4 deletions(-) (limited to 'tox') diff --git a/tox/__init__.py b/tox/__init__.py index 6991c90..baf651b 100644 --- a/tox/__init__.py +++ b/tox/__init__.py @@ -1,5 +1,5 @@ # -__version__ = '2.3.2' +__version__ = '2.4.0.dev1' from .hookspecs import hookspec, hookimpl # noqa diff --git a/tox/_pytestplugin.py b/tox/_pytestplugin.py index f15d2ec..d7bff0c 100644 --- a/tox/_pytestplugin.py +++ b/tox/_pytestplugin.py @@ -195,6 +195,9 @@ class Cmd: return py.std.subprocess.Popen(argv, stdout=stdout, stderr=stderr, **kw) def run(self, *argv): + if argv[0] == "tox" and sys.version_info[:2] < (2,7): + pytest.skip("can not run tests involving calling tox on python2.6. " + "(and python2.6 is about to be deprecated anyway)") argv = [str(x) for x in argv] assert py.path.local.sysfind(str(argv[0])), argv[0] p1 = self.tmpdir.join("stdout") diff --git a/tox/config.py b/tox/config.py index 78d070a..1fd702c 100644 --- a/tox/config.py +++ b/tox/config.py @@ -181,7 +181,7 @@ class PosargsOption: class InstallcmdOption: name = "install_command" type = "argv" - default = "pip install {opts} {packages}" + default = "python -m pip install {opts} {packages}" help = "install command for dependencies and package under test." def postprocess(self, testenv_config, value): @@ -518,6 +518,13 @@ def tox_addoption(parser): help="install package in develop/editable mode") parser.add_testenv_attribute_obj(InstallcmdOption()) + + parser.add_testenv_attribute( + name = "list_dependencies_command", + type = "argv", + default = "python -m pip freeze", + help = "list dependencies for a virtual environment") + parser.add_testenv_attribute_obj(DepOption()) parser.add_testenv_attribute( diff --git a/tox/session.py b/tox/session.py index 029b06b..1d51b92 100644 --- a/tox/session.py +++ b/tox/session.py @@ -537,8 +537,9 @@ class Session: # write out version dependency information action = self.newaction(venv, "envreport") with action: - pip = venv.getcommandpath("pip") - output = venv._pcall([str(pip), "freeze"], + python = venv.getcommandpath("python") + args = venv.envconfig.list_dependencies_command + output = venv._pcall(args, cwd=self.config.toxinidir, action=action) # the output contains a mime-header, skip it -- cgit v1.2.1 From 03dd843fba44bc2fad91da6f2f7bb828a98ab923 Mon Sep 17 00:00:00 2001 From: Oliver Bestwalter Date: Mon, 20 Jun 2016 17:18:50 +0200 Subject: make flakes pass --- tox/_pytestplugin.py | 2 +- tox/config.py | 8 ++++---- tox/session.py | 1 - 3 files changed, 5 insertions(+), 6 deletions(-) (limited to 'tox') diff --git a/tox/_pytestplugin.py b/tox/_pytestplugin.py index 4dfc497..785070d 100644 --- a/tox/_pytestplugin.py +++ b/tox/_pytestplugin.py @@ -195,7 +195,7 @@ class Cmd: return py.std.subprocess.Popen(argv, stdout=stdout, stderr=stderr, **kw) def run(self, *argv): - if argv[0] == "tox" and sys.version_info[:2] < (2,7): + if argv[0] == "tox" and sys.version_info[:2] < (2, 7): pytest.skip("can not run tests involving calling tox on python2.6. " "(and python2.6 is about to be deprecated anyway)") argv = [str(x) for x in argv] diff --git a/tox/config.py b/tox/config.py index 1fd702c..f4c65dc 100644 --- a/tox/config.py +++ b/tox/config.py @@ -520,10 +520,10 @@ def tox_addoption(parser): parser.add_testenv_attribute_obj(InstallcmdOption()) parser.add_testenv_attribute( - name = "list_dependencies_command", - type = "argv", - default = "python -m pip freeze", - help = "list dependencies for a virtual environment") + name="list_dependencies_command", + type="argv", + default="python -m pip freeze", + help="list dependencies for a virtual environment") parser.add_testenv_attribute_obj(DepOption()) diff --git a/tox/session.py b/tox/session.py index 1d51b92..cb5cc66 100644 --- a/tox/session.py +++ b/tox/session.py @@ -537,7 +537,6 @@ class Session: # write out version dependency information action = self.newaction(venv, "envreport") with action: - python = venv.getcommandpath("python") args = venv.envconfig.list_dependencies_command output = venv._pcall(args, cwd=self.config.toxinidir, -- cgit v1.2.1