1
0
mirror of https://github.com/fedora-python/tox-current-env.git synced 2025-01-27 07:06:14 +01:00

Deprecate --print-deps-only in favor of --print-deps-to-file=-

This commit is contained in:
Petr Viktorin 2020-09-15 14:16:40 +02:00
parent ca5bba08a5
commit 93e7f0b16a
3 changed files with 75 additions and 46 deletions

View File

@ -14,11 +14,11 @@ The ``tox-current-env`` plugin adds two options:
An attempt to run this with a Python version that doesn't match will fail An attempt to run this with a Python version that doesn't match will fail
(if ``tox`` is invoked from an Python 3.7 environment, any non 3.7 testenv will fail). (if ``tox`` is invoked from an Python 3.7 environment, any non 3.7 testenv will fail).
``tox --print-deps-only`` / ``--print-deps-to-file`` ``tox --print-deps-to=FILE``
Instead of running any ``commands``, Instead of running any ``commands``,
simply prints the declared dependencies in ``deps`` to the standard output or specified file. simply prints the declared dependencies in ``deps`` to the specified ``FILE``.
This is useful for preparing the current environment for the above. This is useful for preparing the current environment for the above.
``--print-deps-to-file`` will overwrite the file if it already exists. Use ``-`` for ``FILE`` to print to standard output.
Invoking ``tox`` without any of the above options should behave as regular ``tox`` invocation without this plugin. Invoking ``tox`` without any of the above options should behave as regular ``tox`` invocation without this plugin.
Any deviation from this behavior is considered a bug. Any deviation from this behavior is considered a bug.
@ -82,7 +82,7 @@ and ``pip``-installing locally:
Usage Usage
----- -----
When the plugin is installed, use ``tox`` with ``--current-env`` or ``--print-deps-only`` and all the other options as usual. Assuming your ``tox`` is installed on Python 3.7: When the plugin is installed, use ``tox`` with ``--current-env`` or ``--print-deps-to`` and all the other options as usual. Assuming your ``tox`` is installed on Python 3.7:
.. code-block:: console .. code-block:: console
@ -114,7 +114,7 @@ To get list of test dependencies, run:
.. code-block:: console .. code-block:: console
$ tox -e py37 --print-deps-only $ tox -e py37 --print-deps-to -
py37 create: /home/pythonista/projects/holy-grail/tests/.tox/py37 py37 create: /home/pythonista/projects/holy-grail/tests/.tox/py37
py37 installed: ...you can see almost anything here... py37 installed: ...you can see almost anything here...
py37 run-test-pre: PYTHONHASHSEED='3333333333' py37 run-test-pre: PYTHONHASHSEED='3333333333'
@ -159,7 +159,7 @@ Don't mix current-env and regular tox runs
Tox caches the virtualenvs it creates, and doesn't distinguish between Tox caches the virtualenvs it creates, and doesn't distinguish between
regular virtualenvs and ``--current-env``. regular virtualenvs and ``--current-env``.
Don't mix ``tox --current-env`` or ``tox --print-deps-only`` runs Don't mix ``tox --current-env`` or ``tox --print-deps-to`` runs
and regular ``tox`` runs (without the flag). and regular ``tox`` runs (without the flag).
If you ever need to do this, use tox's ``--recreate/-r`` flag to clear the cache. If you ever need to do this, use tox's ``--recreate/-r`` flag to clear the cache.
@ -183,7 +183,7 @@ Read `the documentation for passing environment variables to tox
Other limitations and known bugs Other limitations and known bugs
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The ``installed:`` line in the output of ``tox --print-deps-only`` shows irrelevant output The ``installed:`` line in the output of ``tox --print-deps-to`` shows irrelevant output
(based on the content of the real or faked virtual environment). (based on the content of the real or faked virtual environment).
Regardless of any `Python flags <https://docs.python.org/3/using/cmdline.html>`_ used in the shebang of ``tox``, Regardless of any `Python flags <https://docs.python.org/3/using/cmdline.html>`_ used in the shebang of ``tox``,

View File

@ -3,6 +3,8 @@ import shutil
import subprocess import subprocess
import sys import sys
import tox import tox
import warnings
import argparse
try: try:
import importlib.metadata as importlib_metadata import importlib.metadata as importlib_metadata
@ -24,30 +26,37 @@ def tox_addoption(parser):
action="store_true", action="store_true",
dest="print_deps_only", dest="print_deps_only",
default=False, default=False,
help="Don't run tests, only print the dependencies to stdout", help="Deprecated, equivalent to `--print-deps-to -`",
) )
parser.add_argument( parser.add_argument(
"--print-deps-to",
"--print-deps-to-file", "--print-deps-to-file",
action="store", action="store",
dest="print_deps_path", dest="print_deps_to",
metavar="PATH", type=argparse.FileType('w'),
metavar="FILE",
default=None, default=None,
help="Like --print-deps-only, but to a file. Overwrites the file if it exists.", help="Don't run tests, only print the dependencies to the given file "
+ "(use `-` for stdout)",
) )
@tox.hookimpl @tox.hookimpl
def tox_configure(config): def tox_configure(config):
"""Stores options in the config. Makes all commands external and skips sdist""" """Stores options in the config. Makes all commands external and skips sdist"""
if config.option.print_deps_only and config.option.print_deps_path: if config.option.print_deps_only:
raise tox.exception.ConfigError( warnings.warn(
"--print-deps-only cannot be used together with --print-deps-to-file" "--print-deps-only is deprecated; use `--print-deps-to -`",
DeprecationWarning,
) )
if config.option.print_deps_path is not None: if not config.option.print_deps_to:
config.option.print_deps_only = True config.option.print_deps_to = sys.stdout
with open(config.option.print_deps_path, "w", encoding="utf-8") as f: else:
f.write("") raise tox.exception.ConfigError(
if config.option.current_env or config.option.print_deps_only: "--print-deps-only cannot be used together "
+ "with --print-deps-to"
)
if config.option.current_env or config.option.print_deps_to:
config.skipsdist = True config.skipsdist = True
for testenv in config.envconfigs: for testenv in config.envconfigs:
config.envconfigs[testenv].whitelist_externals = "*" config.envconfigs[testenv].whitelist_externals = "*"
@ -89,16 +98,16 @@ def rm_venv(venv):
def unsupported_raise(config, venv): def unsupported_raise(config, venv):
if config.option.recreate: if config.option.recreate:
return return
regular = not (config.option.current_env or config.option.print_deps_only) regular = not (config.option.current_env or config.option.print_deps_to)
if regular and is_current_env_link(venv): if regular and is_current_env_link(venv):
if hasattr(tox.hookspecs, "tox_cleanup"): if hasattr(tox.hookspecs, "tox_cleanup"):
raise tox.exception.ConfigError( raise tox.exception.ConfigError(
"Looks like previous --current-env or --print-deps-only tox run didn't finish the cleanup. " "Looks like previous --current-env or --print-deps-to tox run didn't finish the cleanup. "
"Run tox run with --recreate (-r) or manually remove the environment in .tox." "Run tox run with --recreate (-r) or manually remove the environment in .tox."
) )
else: else:
raise tox.exception.ConfigError( raise tox.exception.ConfigError(
"Regular tox run after --current-env or --print-deps-only tox run is not supported without --recreate (-r)." "Regular tox run after --current-env or --print-deps-to tox run is not supported without --recreate (-r)."
) )
elif config.option.current_env and is_proper_venv(venv): elif config.option.current_env and is_proper_venv(venv):
raise tox.exception.ConfigError( raise tox.exception.ConfigError(
@ -111,7 +120,7 @@ def tox_testenv_create(venv, action):
"""We create a fake virtualenv with just the symbolic link""" """We create a fake virtualenv with just the symbolic link"""
config = venv.envconfig.config config = venv.envconfig.config
create_fake_env = check_version = config.option.current_env create_fake_env = check_version = config.option.current_env
if config.option.print_deps_only: if config.option.print_deps_to:
if is_any_env(venv): if is_any_env(venv):
# We don't need anything # We don't need anything
return True return True
@ -122,7 +131,7 @@ def tox_testenv_create(venv, action):
# because it's cheaper, faster and won't install stuff # because it's cheaper, faster and won't install stuff
create_fake_env = True create_fake_env = True
if check_version: if check_version:
# With real --current-env, we check this, but not with --print-deps-only only # With real --current-env, we check this, but not with --print-deps-to only
version_info = venv.envconfig.python_info.version_info version_info = venv.envconfig.python_info.version_info
if version_info is None: if version_info is None:
raise tox.exception.InterpreterNotFound(venv.envconfig.basepython) raise tox.exception.InterpreterNotFound(venv.envconfig.basepython)
@ -164,21 +173,21 @@ def tox_testenv_install_deps(venv, action):
"""We don't install anything""" """We don't install anything"""
config = venv.envconfig.config config = venv.envconfig.config
unsupported_raise(config, venv) unsupported_raise(config, venv)
if config.option.current_env or config.option.print_deps_only: if config.option.current_env or config.option.print_deps_to:
return True return True
@tox.hookimpl @tox.hookimpl
def tox_runtest(venv, redirect): def tox_runtest(venv, redirect):
"""If --print-deps-only, prints deps instead of running tests""" """If --print-deps-to, prints deps instead of running tests"""
config = venv.envconfig.config config = venv.envconfig.config
unsupported_raise(config, venv) unsupported_raise(config, venv)
if config.option.print_deps_path is not None: if config.option.print_deps_to:
with open(config.option.print_deps_path, "a", encoding="utf-8") as f: print(
print(*venv.get_resolved_dependencies(), sep="\n", file=f) *venv.get_resolved_dependencies(),
return True sep="\n",
if config.option.print_deps_only: file=config.option.print_deps_to,
print(*venv.get_resolved_dependencies(), sep="\n") )
return True return True

View File

@ -6,6 +6,7 @@ import shutil
import subprocess import subprocess
import sys import sys
import textwrap import textwrap
import warnings
from packaging import version from packaging import version
@ -29,6 +30,12 @@ def projdir(tmp_path, monkeypatch):
monkeypatch.chdir(pwd) monkeypatch.chdir(pwd)
@pytest.fixture(params=('--print-deps-only', '--print-deps-to-file=-', '--print-deps-to=-'))
def print_deps_stdout_arg(request):
"""Argument for printing deps to stdout"""
return request.param
def tox(*args, quiet=True, **kwargs): def tox(*args, quiet=True, **kwargs):
kwargs.setdefault("encoding", "utf-8") kwargs.setdefault("encoding", "utf-8")
kwargs.setdefault("stdout", subprocess.PIPE) kwargs.setdefault("stdout", subprocess.PIPE)
@ -95,8 +102,8 @@ def test_all_toxenv_current_env_skip_missing():
@pytest.mark.parametrize("toxenv", ["py36", "py37", "py38", "py39"]) @pytest.mark.parametrize("toxenv", ["py36", "py37", "py38", "py39"])
def test_print_deps_only(toxenv): def test_print_deps(toxenv, print_deps_stdout_arg):
result = tox("-e", toxenv, "--print-deps-only") result = tox("-e", toxenv, print_deps_stdout_arg)
expected = textwrap.dedent( expected = textwrap.dedent(
f""" f"""
six six
@ -109,8 +116,21 @@ def test_print_deps_only(toxenv):
assert result.stdout == expected assert result.stdout == expected
def test_allenvs_print_deps_only(): @pytest.mark.parametrize("toxenv", ["py36", "py37", "py38", "py39"])
result = tox("--print-deps-only") def test_print_deps_only_deprecated(toxenv):
result = tox(
"-e", toxenv, '--print-deps-only',
env={**os.environ, 'PYTHONWARNINGS': 'always'},
)
waring_text = (
"DeprecationWarning: --print-deps-only is deprecated; "
+ "use `--print-deps-to -`"
)
assert waring_text in result.stderr
def test_allenvs_print_deps(print_deps_stdout_arg):
result = tox(print_deps_stdout_arg)
expected = textwrap.dedent( expected = textwrap.dedent(
""" """
six six
@ -229,7 +249,7 @@ def test_regular_after_current_is_supported():
assert "--recreate" not in result.stderr assert "--recreate" not in result.stderr
def test_regular_after_killed_current_is_not_supported(): def test_regular_after_killed_current_is_not_supported(print_deps_stdout_arg):
# fake broken tox run # fake broken tox run
shutil.rmtree(DOT_TOX, ignore_errors=True) shutil.rmtree(DOT_TOX, ignore_errors=True)
(DOT_TOX / NATIVE_TOXENV / "bin").mkdir(parents=True) (DOT_TOX / NATIVE_TOXENV / "bin").mkdir(parents=True)
@ -240,8 +260,8 @@ def test_regular_after_killed_current_is_not_supported():
assert "--recreate" in result.stderr assert "--recreate" in result.stderr
def test_regular_after_first_deps_only_is_supported(): def test_regular_after_first_print_deps_is_supported(print_deps_stdout_arg):
result = tox("-e", NATIVE_TOXENV, "--print-deps-only") result = tox("-e", NATIVE_TOXENV, print_deps_stdout_arg)
assert result.stdout.splitlines()[0] == "six" assert result.stdout.splitlines()[0] == "six"
result = tox("-e", NATIVE_TOXENV) result = tox("-e", NATIVE_TOXENV)
lines = sorted(result.stdout.splitlines()[:1]) lines = sorted(result.stdout.splitlines()[:1])
@ -283,18 +303,18 @@ def test_current_recreate_after_regular():
assert result.stdout.splitlines()[0] == NATIVE_EXEC_PREFIX_MSG assert result.stdout.splitlines()[0] == NATIVE_EXEC_PREFIX_MSG
def test_current_after_deps_only(): def test_current_after_print_deps(print_deps_stdout_arg):
# this is quite fast, so we can do it several times # this is quite fast, so we can do it several times
for _ in range(3): for _ in range(3):
result = tox("-e", NATIVE_TOXENV, "--print-deps-only") result = tox("-e", NATIVE_TOXENV, print_deps_stdout_arg)
assert "bin/python" not in result.stdout assert "bin/python" not in result.stdout
assert "six" in result.stdout assert "six" in result.stdout
result = tox("-re", NATIVE_TOXENV, "--current-env") result = tox("-re", NATIVE_TOXENV, "--current-env")
assert result.stdout.splitlines()[0] == NATIVE_EXEC_PREFIX_MSG assert result.stdout.splitlines()[0] == NATIVE_EXEC_PREFIX_MSG
def test_regular_recreate_after_deps_only(): def test_regular_recreate_after_print_deps(print_deps_stdout_arg):
result = tox("-e", NATIVE_TOXENV, "--print-deps-only") result = tox("-e", NATIVE_TOXENV, print_deps_stdout_arg)
assert "bin/python" not in result.stdout assert "bin/python" not in result.stdout
assert "six" in result.stdout assert "six" in result.stdout
@ -304,12 +324,12 @@ def test_regular_recreate_after_deps_only():
assert sitelib.is_dir() assert sitelib.is_dir()
assert len(list(sitelib.glob("test-*.dist-info"))) == 1 assert len(list(sitelib.glob("test-*.dist-info"))) == 1
result = tox("-e", NATIVE_TOXENV, "--print-deps-only") result = tox("-e", NATIVE_TOXENV, print_deps_stdout_arg)
assert "bin/python" not in result.stdout assert "bin/python" not in result.stdout
assert "six" in result.stdout assert "six" in result.stdout
def test_print_deps_without_python_command(tmp_path): def test_print_deps_without_python_command(tmp_path, print_deps_stdout_arg):
bin = tmp_path / "bin" bin = tmp_path / "bin"
bin.mkdir() bin.mkdir()
tox_link = bin / "tox" tox_link = bin / "tox"
@ -317,7 +337,7 @@ def test_print_deps_without_python_command(tmp_path):
tox_link.symlink_to(tox_path) tox_link.symlink_to(tox_path)
env = {**os.environ, "PATH": str(bin)} env = {**os.environ, "PATH": str(bin)}
result = tox("-e", NATIVE_TOXENV, "--print-deps-only", env=env) result = tox("-e", NATIVE_TOXENV, print_deps_stdout_arg, env=env)
expected = textwrap.dedent( expected = textwrap.dedent(
f""" f"""
six six