Skip to content

Commit

Permalink
Allow bypassing the logging setup via the Python API (#1904)
Browse files Browse the repository at this point in the history
Signed-off-by: Bernat Gabor <[email protected]>
  • Loading branch information
gaborbernat authored Jul 24, 2020
1 parent 012d5b5 commit 3f45db5
Show file tree
Hide file tree
Showing 8 changed files with 57 additions and 25 deletions.
File renamed without changes.
2 changes: 2 additions & 0 deletions docs/changelog/1896.bugfix.rst
Original file line number Diff line number Diff line change
@@ -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`.
3 changes: 2 additions & 1 deletion src/virtualenv/__init__.py
Original file line number Diff line number Diff line change
@@ -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",
)
48 changes: 32 additions & 16 deletions src/virtualenv/run/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand All @@ -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)

Expand Down Expand Up @@ -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(
Expand All @@ -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",
)
6 changes: 3 additions & 3 deletions tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -196,8 +196,8 @@ def coverage_env(monkeypatch, link, request):
# we inject right after creation, we cannot collect coverage on site.py - used for helper scripts, such as debug
from virtualenv import run

def via_cli(args, options):
session = prev_run(args, options)
def _session_via_cli(args, options, setup_logging):
session = prev_run(args, options, setup_logging)
old_run = session.creator.run

def create_run():
Expand All @@ -211,7 +211,7 @@ def create_run():

obj = {"cov": None}
prev_run = run.session_via_cli
monkeypatch.setattr(run, "session_via_cli", via_cli)
monkeypatch.setattr(run, "session_via_cli", _session_via_cli)

def finish():
cov = obj["cov"]
Expand Down
4 changes: 2 additions & 2 deletions tests/unit/config/test___main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
4 changes: 2 additions & 2 deletions tests/unit/create/test_creator.py
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
15 changes: 14 additions & 1 deletion tests/unit/test_run.py
Original file line number Diff line number Diff line change
@@ -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):
Expand All @@ -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

0 comments on commit 3f45db5

Please sign in to comment.