diff options
| author | Alexander Schepanovski <suor.web@gmail.com> | 2014-06-20 18:10:04 +0800 |
|---|---|---|
| committer | Alexander Schepanovski <suor.web@gmail.com> | 2014-06-20 18:10:04 +0800 |
| commit | c4166e3a4924f860b02c6886a955f3b51bb4f689 (patch) | |
| tree | 5578de719d8a56f3542814dfa5787d397e54c5aa | |
| parent | bfb9423685f02a98801981a60720e21dce694b67 (diff) | |
| download | tox-c4166e3a4924f860b02c6886a955f3b51bb4f689.tar.gz | |
First stab at multidimensional config
| -rw-r--r-- | tox/_config.py | 72 |
1 files changed, 56 insertions, 16 deletions
diff --git a/tox/_config.py b/tox/_config.py index 4f89d00..5935f74 100644 --- a/tox/_config.py +++ b/tox/_config.py @@ -303,10 +303,18 @@ class parseini: config.skipsdist = reader.getbool(toxsection, "skipsdist", all_develop) - def _makeenvconfig(self, name, section, subs, config): + # interpolate missing configs + for name in config.envlist: + if name not in config.envconfigs: + config.envconfigs[name] = \ + self._makeenvconfig(name, "testenv", reader._subs, config, + factors=name.split('-')) + + def _makeenvconfig(self, name, section, subs, config, factors=()): vc = VenvConfig(envname=name) vc.config = config - reader = IniReader(self._cfg, fallbacksections=["testenv"]) + reader = IniReader(self._cfg, fallbacksections=["testenv"], + factors=factors) reader.addsubstitutions(**subs) vc.develop = not config.option.installpkg and \ reader.getbool(section, "usedevelop", config.option.develop) @@ -391,16 +399,33 @@ class parseini: if not env: env = os.environ.get("TOXENV", None) if not env: - envlist = reader.getlist(toxsection, "envlist", sep=",") + envstr = reader.getdefault(toxsection, "envlist", default="", + replace=False) + envlist = self._expand_envstr(envstr) if not envlist: envlist = self.config.envconfigs.keys() return envlist + # TODO: move envsplit magic to _split_env() envlist = _split_env(env) if "ALL" in envlist: envlist = list(self.config.envconfigs) envlist.sort() return envlist + def _expand_envstr(self, envstr): + from itertools import groupby, product, chain + + # split by commas not in groups + tokens = re.split(r'(\{[^}]+\})|,', envstr) + envlist = [''.join(g).strip() for k, g in groupby(tokens, key=bool) if k] + + def expand(env): + tokens = re.split(r'\{([^}]+)\}', env) + parts = [token.split(',') for token in tokens] + return [''.join(variant) for variant in product(*parts)] + + return list(chain(*map(expand, envlist))) + def _replace_forced_dep(self, name, config): """ Override the given dependency config name taking --force-dep-version @@ -468,9 +493,10 @@ RE_ITEM_REF = re.compile( class IniReader: - def __init__(self, cfgparser, fallbacksections=None): + def __init__(self, cfgparser, fallbacksections=None, factors=()): self._cfg = cfgparser self.fallbacksections = fallbacksections or [] + self.factors = factors self._subs = {} self._subststack = [] @@ -586,18 +612,19 @@ class IniReader: return s def getdefault(self, section, name, default=None, replace=True): - try: - x = self._cfg[section][name] - except KeyError: - for fallbacksection in self.fallbacksections: - try: - x = self._cfg[fallbacksection][name] - except KeyError: - pass - else: - break - else: - x = default + x = None + for s in [section] + self.fallbacksections: + try: + x = self._cfg[s][name] + break + except KeyError: + continue + + if x is None: + x = default + else: + x = self._apply_factors(x) + if replace and x and hasattr(x, 'replace'): self._subststack.append((section, name)) try: @@ -607,6 +634,19 @@ class IniReader: #print "getdefault", section, name, "returned", repr(x) return x + def _apply_factors(self, s): + def factor_line(line): + m = re.search(r'^(!)?(\w+)?\:\s*(.+)', line) + if not m: + return line + + negate, factor, line = m.groups() + if bool(negate) ^ (factor in self.factors): + return line + + lines = s.strip().splitlines() + return '\n'.join(filter(None, map(factor_line, lines))) + def _replace_env(self, match): match_value = match.group('substitution_value') if not match_value: |
