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:
parent
ca5bba08a5
commit
93e7f0b16a
14
README.rst
14
README.rst
@ -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``,
|
||||||
|
@ -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
|
||||||
|
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
Loading…
Reference in New Issue
Block a user