diff --git a/README.md b/README.md index 803e04e..7cbd506 100644 --- a/README.md +++ b/README.md @@ -150,6 +150,29 @@ python = ... ``` +You can also specify without minor versions in the `python` configuration key. + +`tox.ini`: +```ini +[tox] +envlist = py2, py3, pypy2, pypy3 + +[gh-actions] +python = + 2: py2 + 3: py3, mypy + # pypy2 and pypy3 are still supported for backward compatibility + pypy-2: pypy2 + pypy-3: pypy3 + +[testenv] +... +``` + +If there are multiple matching Python versions in the configuration, only the most precise one is used. +For example, if you are running CPython 3.8 and `gh-actions.python` has both `3` and `3.8`, +tox-gh-actions gets factors only from the key `3.8`. + #### Factor-Conditional Settings: Environment Variable You can also use environment variable to decide which environment to run. The following is an example to install different dependency based on platform. diff --git a/src/tox_gh_actions/plugin.py b/src/tox_gh_actions/plugin.py index b04d24d..fc8066a 100644 --- a/src/tox_gh_actions/plugin.py +++ b/src/tox_gh_actions/plugin.py @@ -32,13 +32,13 @@ def tox_configure(config): verbosity2("original envlist_default: {}".format(config.envlist_default)) verbosity2("original envlist: {}".format(config.envlist)) - version = get_python_version() - verbosity2("Python version: {}".format(version)) + versions = get_python_version_keys() + verbosity2("Python versions: {}".format(versions)) gh_actions_config = parse_config(config._cfg.sections) verbosity2("tox-gh-actions config: {}".format(gh_actions_config)) - factors = get_factors(gh_actions_config, version) + factors = get_factors(gh_actions_config, versions) verbosity2("using the following factors to decide envlist: {}".format(factors)) envlist = get_envlist_from_factors(config.envlist, factors) @@ -76,12 +76,15 @@ def parse_config(config): } -def get_factors(gh_actions_config, version): - # type: (Dict[str, Dict[str, Any]], str) -> List[str] +def get_factors(gh_actions_config, versions): + # type: (Dict[str, Dict[str, Any]], Iterable[str]) -> List[str] """Get a list of factors""" factors = [] # type: List[List[str]] - if version in gh_actions_config["python"]: - factors.append(gh_actions_config["python"][version]) + for version in versions: + if version in gh_actions_config["python"]: + verbosity2("got factors for Python version: {}".format(version)) + factors.append(gh_actions_config["python"][version]) + break # Shoudn't check remaining versions for env, env_config in gh_actions_config.get("env", {}).items(): if env in os.environ: env_value = os.environ[env] @@ -103,20 +106,30 @@ def get_envlist_from_factors(envlist, factors): return result -def get_python_version(): - # type: () -> str - """Get Python version running in string (e.g,. 3.8) +def get_python_version_keys(): + # type: () -> List[str] + """Get Python version in string for getting factors from gh-action's config - - CPython => 2.7, 3.8, ... - - PyPy => pypy-2.7, pypy-3.7 + Examples: + - CPython 2.7.z => [2.7, 2] + - CPython 3.8.z => [3.8, 3] + - PyPy 2.7 (v7.3.z) => [pypy-2.7, pypy-2, pypy2] + - PyPy 3.6 (v7.3.z) => [pypy-3.6, pypy-3, pypy3] + + Support of "pypy2" and "pypy3" is for backward compatibility with + tox-gh-actions v2.2.0 and before. """ + major_version = str(sys.version_info[0]) + major_minor_version = ".".join([str(i) for i in sys.version_info[:2]]) if "PyPy" in sys.version: - version_prefix = "pypy-" + return [ + "pypy-" + major_minor_version, + "pypy-" + major_version, + "pypy" + major_version, + ] else: # Assume this is running on CPython - version_prefix = "" - version = ".".join([str(i) for i in sys.version_info[:2]]) - return version_prefix + version + return [major_minor_version, major_version] def is_running_on_actions(): diff --git a/tests/test_plugin.py b/tests/test_plugin.py index 72bd62f..1b5b19b 100644 --- a/tests/test_plugin.py +++ b/tests/test_plugin.py @@ -83,10 +83,37 @@ def test_parse_config(config, expected): }, "unknown": {}, }, - "2.7", + ["2.7", "2"], {}, ["py27", "flake8"], ), + # Get factors using less precise Python version + ( + { + "python": { + "2": ["py2", "flake8"], + "3": ["py3", "flake8"], + }, + "unknown": {}, + }, + ["3.8", "3"], + {}, + ["py3", "flake8"], + ), + # Get factors only from the most precise Python version + ( + { + "python": { + "2": ["py2", "flake8"], + "3": ["py3", "flake8"], + "3.9": ["py39"], + }, + "unknown": {}, + }, + ["3.9", "3"], + {}, + ["py39"], + ), ( { "python": { @@ -100,7 +127,7 @@ def test_parse_config(config, expected): }, }, }, - "2.7", + ["2.7", "2"], { "SAMPLE": "VALUE1", "HOGE": "VALUE3", @@ -124,7 +151,7 @@ def test_parse_config(config, expected): }, }, }, - "2.7", + ["2.7", "2"], { "SAMPLE": "VALUE1", "HOGE": "VALUE3", @@ -153,7 +180,7 @@ def test_parse_config(config, expected): }, }, }, - "2.7", + ["2.7", "2"], { "SAMPLE": "VALUE1", "HOGE": "VALUE3", @@ -179,7 +206,7 @@ def test_parse_config(config, expected): }, "unknown": {}, }, - "2.7", + ["2.7", "2"], { "SAMPLE": "VALUE3", }, @@ -198,7 +225,7 @@ def test_parse_config(config, expected): }, "unknown": {}, }, - "3.8", + ["3.8", "3"], { "SAMPLE": "VALUE2", }, @@ -210,7 +237,7 @@ def test_parse_config(config, expected): "3.8": ["py38", "flake8"], }, }, - "2.7", + ["2.7", "2"], {}, [], ), @@ -283,26 +310,26 @@ def test_get_envlist_from_factors(envlist, factors, expected): ( "3.8.1 (default, Jan 22 2020, 06:38:00) \n[GCC 9.2.0]", (3, 8, 1, "final", 0), - "3.8", + ["3.8", "3"], ), ( "3.6.9 (1608da62bfc7, Dec 23 2019, 10:50:04)\n" "[PyPy 7.3.0 with GCC 7.3.1 20180303 (Red Hat 7.3.1-5)]", (3, 6, 9, "final", 0), - "pypy-3.6", + ["pypy-3.6", "pypy-3", "pypy3"], ), ( "2.7.13 (724f1a7d62e8, Dec 23 2019, 15:36:24)\n" "[PyPy 7.3.0 with GCC 7.3.1 20180303 (Red Hat 7.3.1-5)]", (2, 7, 13, "final", 42), - "pypy-2.7", + ["pypy-2.7", "pypy-2", "pypy2"], ), ], ) -def test_get_version(mocker, version, info, expected): +def test_get_version_keys(mocker, version, info, expected): mocker.patch("tox_gh_actions.plugin.sys.version", version) mocker.patch("tox_gh_actions.plugin.sys.version_info", info) - assert plugin.get_python_version() == expected + assert plugin.get_python_version_keys() == expected @pytest.mark.parametrize(