1
0
mirror of https://github.com/fedora-python/tox-current-env.git synced 2025-01-26 22:56:15 +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
(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``,
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.
``--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.
Any deviation from this behavior is considered a bug.
@ -82,7 +82,7 @@ and ``pip``-installing locally:
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
@ -114,7 +114,7 @@ To get list of test dependencies, run:
.. 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 installed: ...you can see almost anything here...
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
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).
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
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
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).
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 sys
import tox
import warnings
import argparse
try:
import importlib.metadata as importlib_metadata
@ -24,30 +26,37 @@ def tox_addoption(parser):
action="store_true",
dest="print_deps_only",
default=False,
help="Don't run tests, only print the dependencies to stdout",
help="Deprecated, equivalent to `--print-deps-to -`",
)
parser.add_argument(
"--print-deps-to",
"--print-deps-to-file",
action="store",
dest="print_deps_path",
metavar="PATH",
dest="print_deps_to",
type=argparse.FileType('w'),
metavar="FILE",
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
def tox_configure(config):
"""Stores options in the config. Makes all commands external and skips sdist"""
if config.option.print_deps_only and config.option.print_deps_path:
raise tox.exception.ConfigError(
"--print-deps-only cannot be used together with --print-deps-to-file"
if config.option.print_deps_only:
warnings.warn(
"--print-deps-only is deprecated; use `--print-deps-to -`",
DeprecationWarning,
)
if config.option.print_deps_path is not None:
config.option.print_deps_only = True
with open(config.option.print_deps_path, "w", encoding="utf-8") as f:
f.write("")
if config.option.current_env or config.option.print_deps_only:
if not config.option.print_deps_to:
config.option.print_deps_to = sys.stdout
else:
raise tox.exception.ConfigError(
"--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
for testenv in config.envconfigs:
config.envconfigs[testenv].whitelist_externals = "*"
@ -89,16 +98,16 @@ def rm_venv(venv):
def unsupported_raise(config, venv):
if config.option.recreate:
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 hasattr(tox.hookspecs, "tox_cleanup"):
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."
)
else:
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):
raise tox.exception.ConfigError(
@ -111,7 +120,7 @@ def tox_testenv_create(venv, action):
"""We create a fake virtualenv with just the symbolic link"""
config = venv.envconfig.config
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):
# We don't need anything
return True
@ -122,7 +131,7 @@ def tox_testenv_create(venv, action):
# because it's cheaper, faster and won't install stuff
create_fake_env = True
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
if version_info is None:
raise tox.exception.InterpreterNotFound(venv.envconfig.basepython)
@ -164,21 +173,21 @@ def tox_testenv_install_deps(venv, action):
"""We don't install anything"""
config = venv.envconfig.config
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
@tox.hookimpl
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
unsupported_raise(config, venv)
if config.option.print_deps_path is not None:
with open(config.option.print_deps_path, "a", encoding="utf-8") as f:
print(*venv.get_resolved_dependencies(), sep="\n", file=f)
return True
if config.option.print_deps_only:
print(*venv.get_resolved_dependencies(), sep="\n")
if config.option.print_deps_to:
print(
*venv.get_resolved_dependencies(),
sep="\n",
file=config.option.print_deps_to,
)
return True

View File

@ -6,6 +6,7 @@ import shutil
import subprocess
import sys
import textwrap
import warnings
from packaging import version
@ -29,6 +30,12 @@ def projdir(tmp_path, monkeypatch):
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):
kwargs.setdefault("encoding", "utf-8")
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"])
def test_print_deps_only(toxenv):
result = tox("-e", toxenv, "--print-deps-only")
def test_print_deps(toxenv, print_deps_stdout_arg):
result = tox("-e", toxenv, print_deps_stdout_arg)
expected = textwrap.dedent(
f"""
six
@ -109,8 +116,21 @@ def test_print_deps_only(toxenv):
assert result.stdout == expected
def test_allenvs_print_deps_only():
result = tox("--print-deps-only")
@pytest.mark.parametrize("toxenv", ["py36", "py37", "py38", "py39"])
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(
"""
six
@ -229,7 +249,7 @@ def test_regular_after_current_is_supported():
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
shutil.rmtree(DOT_TOX, ignore_errors=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
def test_regular_after_first_deps_only_is_supported():
result = tox("-e", NATIVE_TOXENV, "--print-deps-only")
def test_regular_after_first_print_deps_is_supported(print_deps_stdout_arg):
result = tox("-e", NATIVE_TOXENV, print_deps_stdout_arg)
assert result.stdout.splitlines()[0] == "six"
result = tox("-e", NATIVE_TOXENV)
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
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
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 "six" in result.stdout
result = tox("-re", NATIVE_TOXENV, "--current-env")
assert result.stdout.splitlines()[0] == NATIVE_EXEC_PREFIX_MSG
def test_regular_recreate_after_deps_only():
result = tox("-e", NATIVE_TOXENV, "--print-deps-only")
def test_regular_recreate_after_print_deps(print_deps_stdout_arg):
result = tox("-e", NATIVE_TOXENV, print_deps_stdout_arg)
assert "bin/python" not in result.stdout
assert "six" in result.stdout
@ -304,12 +324,12 @@ def test_regular_recreate_after_deps_only():
assert sitelib.is_dir()
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 "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.mkdir()
tox_link = bin / "tox"
@ -317,7 +337,7 @@ def test_print_deps_without_python_command(tmp_path):
tox_link.symlink_to(tox_path)
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(
f"""
six