diff --git a/docs/changelog/1882.bufix.rst b/docs/changelog/1882.bugfix.rst similarity index 100% rename from docs/changelog/1882.bufix.rst rename to docs/changelog/1882.bugfix.rst diff --git a/docs/changelog/1896.bugfix.rst b/docs/changelog/1896.bugfix.rst new file mode 100644 index 000000000..923864c76 --- /dev/null +++ b/docs/changelog/1896.bugfix.rst @@ -0,0 +1,2 @@ +Provide ``setup_logging`` flag to python API so that users can bypass logging handling if their application already +performs this - by :user:`gaborbernat`. diff --git a/src/virtualenv/__init__.py b/src/virtualenv/__init__.py index c72643f02..5f74e3ef2 100644 --- a/src/virtualenv/__init__.py +++ b/src/virtualenv/__init__.py @@ -1,9 +1,10 @@ from __future__ import absolute_import, unicode_literals -from .run import cli_run +from .run import cli_run, session_via_cli from .version import __version__ __all__ = ( "__version__", "cli_run", + "session_via_cli", ) diff --git a/src/virtualenv/run/__init__.py b/src/virtualenv/run/__init__.py index 2fa7d0d3b..5c1e1b0f7 100644 --- a/src/virtualenv/run/__init__.py +++ b/src/virtualenv/run/__init__.py @@ -14,30 +14,39 @@ from .plugin.seeders import SeederSelector -def cli_run(args, options=None): - """Create a virtual environment given some command line interface arguments +def cli_run(args, options=None, setup_logging=True): + """ + Create a virtual environment given some command line interface arguments. :param args: the command line arguments :param options: passing in a ``VirtualEnvOptions`` object allows return of the parsed options + :param setup_logging: ``True`` if setup logging handlers, ``False`` to use handlers already registered :return: the session object of the creation (its structure for now is experimental and might change on short notice) """ - session = session_via_cli(args, options) - with session: - session.run() - return session + of_session = session_via_cli(args, options, setup_logging) + with of_session: + of_session.run() + return of_session + +def session_via_cli(args, options=None, setup_logging=True): + """ + Create a virtualenv session (same as cli_run, but this does not perform the creation). Use this if you just want to + query what the virtual environment would look like, but not actually create it. -# noinspection PyProtectedMember -def session_via_cli(args, options=None): - parser, elements = build_parser(args, options) + :param args: the command line arguments + :param options: passing in a ``VirtualEnvOptions`` object allows return of the parsed options + :param setup_logging: ``True`` if setup logging handlers, ``False`` to use handlers already registered + :return: the session object of the creation (its structure for now is experimental and might change on short notice) + """ + parser, elements = build_parser(args, options, setup_logging) options = parser.parse_args(args) creator, seeder, activators = tuple(e.create(options) for e in elements) # create types - session = Session(options.verbosity, options.app_data, parser._interpreter, creator, seeder, activators) - return session + of_session = Session(options.verbosity, options.app_data, parser._interpreter, creator, seeder, activators) # noqa + return of_session -# noinspection PyProtectedMember -def build_parser(args=None, options=None): +def build_parser(args=None, options=None, setup_logging=True): parser = VirtualEnvConfigParser(options) add_version_flag(parser) parser.add_argument( @@ -47,7 +56,7 @@ def build_parser(args=None, options=None): default=False, help="on failure also display the stacktrace internals of virtualenv", ) - _do_report_setup(parser, args) + _do_report_setup(parser, args, setup_logging) options = load_app_data(args, parser, options) handle_extra_commands(options) @@ -121,7 +130,7 @@ def add_version_flag(parser): ) -def _do_report_setup(parser, args): +def _do_report_setup(parser, args, setup_logging): level_map = ", ".join("{}={}".format(logging.getLevelName(l), c) for c, l in sorted(list(LEVELS.items()))) msg = "verbosity = verbose - quiet, default {}, mapping => {}" verbosity_group = parser.add_argument_group( @@ -131,4 +140,11 @@ def _do_report_setup(parser, args): verbosity.add_argument("-v", "--verbose", action="count", dest="verbose", help="increase verbosity", default=2) verbosity.add_argument("-q", "--quiet", action="count", dest="quiet", help="decrease verbosity", default=0) option, _ = parser.parse_known_args(args) - setup_report(option.verbosity) + if setup_logging: + setup_report(option.verbosity) + + +__all__ = ( + "cli_run", + "session_via_cli", +) diff --git a/tests/unit/config/test___main__.py b/tests/unit/config/test___main__.py index 3aad47594..adf346422 100644 --- a/tests/unit/config/test___main__.py +++ b/tests/unit/config/test___main__.py @@ -24,8 +24,8 @@ def _func(exception): prev_session = session_via_cli - def _session_via_cli(args, options=None): - prev_session(args, options) + def _session_via_cli(args, options=None, setup_logging=True): + prev_session(args, options, setup_logging) raise exception mocker.patch("virtualenv.run.session_via_cli", side_effect=_session_via_cli) diff --git a/tests/unit/create/test_creator.py b/tests/unit/create/test_creator.py index 10090c750..9e4bc825b 100644 --- a/tests/unit/create/test_creator.py +++ b/tests/unit/create/test_creator.py @@ -250,8 +250,8 @@ def test_venv_fails_not_inline(tmp_path, capsys, mocker): if os.geteuid() == 0: pytest.skip("no way to check permission restriction when running under root") - def _session_via_cli(args, options=None): - session = session_via_cli(args, options) + def _session_via_cli(args, options=None, setup_logging=True): + session = session_via_cli(args, options, setup_logging) assert session.creator.can_be_inline is False return session diff --git a/tests/unit/test_run.py b/tests/unit/test_run.py index 436e5eba6..53849f59a 100644 --- a/tests/unit/test_run.py +++ b/tests/unit/test_run.py @@ -1,10 +1,12 @@ from __future__ import absolute_import, unicode_literals +import logging + import pytest import six from virtualenv import __version__ -from virtualenv.run import cli_run +from virtualenv.run import cli_run, session_via_cli def test_help(capsys): @@ -31,3 +33,14 @@ def test_version(capsys): import virtualenv assert virtualenv.__file__ in content + + +@pytest.mark.parametrize("on", [True, False]) +def test_logging_setup(caplog, on): + caplog.set_level(logging.DEBUG) + session_via_cli(["env"], setup_logging=on) + # DEBUG only level output is generated during this phase, default output is WARN, so if on no records should be + if on: + assert not caplog.records + else: + assert caplog.records