Skip to content

Commit 3f45db5

Browse files
authored
Allow bypassing the logging setup via the Python API (#1904)
Signed-off-by: Bernat Gabor <bgabor8@bloomberg.net>
1 parent 012d5b5 commit 3f45db5

File tree

8 files changed

+57
-25
lines changed

8 files changed

+57
-25
lines changed
File renamed without changes.

docs/changelog/1896.bugfix.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Provide ``setup_logging`` flag to python API so that users can bypass logging handling if their application already
2+
performs this - by :user:`gaborbernat`.

src/virtualenv/__init__.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
from __future__ import absolute_import, unicode_literals
22

3-
from .run import cli_run
3+
from .run import cli_run, session_via_cli
44
from .version import __version__
55

66
__all__ = (
77
"__version__",
88
"cli_run",
9+
"session_via_cli",
910
)

src/virtualenv/run/__init__.py

Lines changed: 32 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -14,30 +14,39 @@
1414
from .plugin.seeders import SeederSelector
1515

1616

17-
def cli_run(args, options=None):
18-
"""Create a virtual environment given some command line interface arguments
17+
def cli_run(args, options=None, setup_logging=True):
18+
"""
19+
Create a virtual environment given some command line interface arguments.
1920
2021
:param args: the command line arguments
2122
:param options: passing in a ``VirtualEnvOptions`` object allows return of the parsed options
23+
:param setup_logging: ``True`` if setup logging handlers, ``False`` to use handlers already registered
2224
:return: the session object of the creation (its structure for now is experimental and might change on short notice)
2325
"""
24-
session = session_via_cli(args, options)
25-
with session:
26-
session.run()
27-
return session
26+
of_session = session_via_cli(args, options, setup_logging)
27+
with of_session:
28+
of_session.run()
29+
return of_session
30+
2831

32+
def session_via_cli(args, options=None, setup_logging=True):
33+
"""
34+
Create a virtualenv session (same as cli_run, but this does not perform the creation). Use this if you just want to
35+
query what the virtual environment would look like, but not actually create it.
2936
30-
# noinspection PyProtectedMember
31-
def session_via_cli(args, options=None):
32-
parser, elements = build_parser(args, options)
37+
:param args: the command line arguments
38+
:param options: passing in a ``VirtualEnvOptions`` object allows return of the parsed options
39+
:param setup_logging: ``True`` if setup logging handlers, ``False`` to use handlers already registered
40+
:return: the session object of the creation (its structure for now is experimental and might change on short notice)
41+
"""
42+
parser, elements = build_parser(args, options, setup_logging)
3343
options = parser.parse_args(args)
3444
creator, seeder, activators = tuple(e.create(options) for e in elements) # create types
35-
session = Session(options.verbosity, options.app_data, parser._interpreter, creator, seeder, activators)
36-
return session
45+
of_session = Session(options.verbosity, options.app_data, parser._interpreter, creator, seeder, activators) # noqa
46+
return of_session
3747

3848

39-
# noinspection PyProtectedMember
40-
def build_parser(args=None, options=None):
49+
def build_parser(args=None, options=None, setup_logging=True):
4150
parser = VirtualEnvConfigParser(options)
4251
add_version_flag(parser)
4352
parser.add_argument(
@@ -47,7 +56,7 @@ def build_parser(args=None, options=None):
4756
default=False,
4857
help="on failure also display the stacktrace internals of virtualenv",
4958
)
50-
_do_report_setup(parser, args)
59+
_do_report_setup(parser, args, setup_logging)
5160
options = load_app_data(args, parser, options)
5261
handle_extra_commands(options)
5362

@@ -121,7 +130,7 @@ def add_version_flag(parser):
121130
)
122131

123132

124-
def _do_report_setup(parser, args):
133+
def _do_report_setup(parser, args, setup_logging):
125134
level_map = ", ".join("{}={}".format(logging.getLevelName(l), c) for c, l in sorted(list(LEVELS.items())))
126135
msg = "verbosity = verbose - quiet, default {}, mapping => {}"
127136
verbosity_group = parser.add_argument_group(
@@ -131,4 +140,11 @@ def _do_report_setup(parser, args):
131140
verbosity.add_argument("-v", "--verbose", action="count", dest="verbose", help="increase verbosity", default=2)
132141
verbosity.add_argument("-q", "--quiet", action="count", dest="quiet", help="decrease verbosity", default=0)
133142
option, _ = parser.parse_known_args(args)
134-
setup_report(option.verbosity)
143+
if setup_logging:
144+
setup_report(option.verbosity)
145+
146+
147+
__all__ = (
148+
"cli_run",
149+
"session_via_cli",
150+
)

tests/conftest.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -196,8 +196,8 @@ def coverage_env(monkeypatch, link, request):
196196
# we inject right after creation, we cannot collect coverage on site.py - used for helper scripts, such as debug
197197
from virtualenv import run
198198

199-
def via_cli(args, options):
200-
session = prev_run(args, options)
199+
def _session_via_cli(args, options, setup_logging):
200+
session = prev_run(args, options, setup_logging)
201201
old_run = session.creator.run
202202

203203
def create_run():
@@ -211,7 +211,7 @@ def create_run():
211211

212212
obj = {"cov": None}
213213
prev_run = run.session_via_cli
214-
monkeypatch.setattr(run, "session_via_cli", via_cli)
214+
monkeypatch.setattr(run, "session_via_cli", _session_via_cli)
215215

216216
def finish():
217217
cov = obj["cov"]

tests/unit/config/test___main__.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,8 @@ def _func(exception):
2424

2525
prev_session = session_via_cli
2626

27-
def _session_via_cli(args, options=None):
28-
prev_session(args, options)
27+
def _session_via_cli(args, options=None, setup_logging=True):
28+
prev_session(args, options, setup_logging)
2929
raise exception
3030

3131
mocker.patch("virtualenv.run.session_via_cli", side_effect=_session_via_cli)

tests/unit/create/test_creator.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -250,8 +250,8 @@ def test_venv_fails_not_inline(tmp_path, capsys, mocker):
250250
if os.geteuid() == 0:
251251
pytest.skip("no way to check permission restriction when running under root")
252252

253-
def _session_via_cli(args, options=None):
254-
session = session_via_cli(args, options)
253+
def _session_via_cli(args, options=None, setup_logging=True):
254+
session = session_via_cli(args, options, setup_logging)
255255
assert session.creator.can_be_inline is False
256256
return session
257257

tests/unit/test_run.py

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
from __future__ import absolute_import, unicode_literals
22

3+
import logging
4+
35
import pytest
46
import six
57

68
from virtualenv import __version__
7-
from virtualenv.run import cli_run
9+
from virtualenv.run import cli_run, session_via_cli
810

911

1012
def test_help(capsys):
@@ -31,3 +33,14 @@ def test_version(capsys):
3133
import virtualenv
3234

3335
assert virtualenv.__file__ in content
36+
37+
38+
@pytest.mark.parametrize("on", [True, False])
39+
def test_logging_setup(caplog, on):
40+
caplog.set_level(logging.DEBUG)
41+
session_via_cli(["env"], setup_logging=on)
42+
# DEBUG only level output is generated during this phase, default output is WARN, so if on no records should be
43+
if on:
44+
assert not caplog.records
45+
else:
46+
assert caplog.records

0 commit comments

Comments
 (0)