Skip to content

Commit 1b9b1f8

Browse files
authored
try to reset log-level after setting it (#10800)
1 parent be1b529 commit 1b9b1f8

File tree

8 files changed

+55
-35
lines changed

8 files changed

+55
-35
lines changed

dvc/cli/__init__.py

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,8 @@ def main(argv=None): # noqa: C901, PLR0912, PLR0915
157157
Returns:
158158
int: command's return code.
159159
"""
160+
from contextlib import ExitStack
161+
160162
from dvc._debug import debugtools
161163
from dvc.config import ConfigError
162164
from dvc.exceptions import DvcException, NotDvcRepoError
@@ -173,12 +175,11 @@ def main(argv=None): # noqa: C901, PLR0912, PLR0915
173175
logging.disable(logging.INFO)
174176

175177
args = None
176-
177-
outer_log_level = logger.level
178-
level = None
178+
stack = ExitStack()
179179
try:
180180
args = parse_args(argv)
181181

182+
level = None
182183
if args.quiet:
183184
level = logging.CRITICAL
184185
elif args.verbose == 1:
@@ -187,7 +188,7 @@ def main(argv=None): # noqa: C901, PLR0912, PLR0915
187188
level = logging.TRACE # type: ignore[attr-defined]
188189

189190
if level is not None:
190-
set_loggers_level(level)
191+
stack.enter_context(set_loggers_level(level))
191192

192193
if level and level <= logging.DEBUG:
193194
from platform import platform, python_implementation, python_version
@@ -247,7 +248,7 @@ def main(argv=None): # noqa: C901, PLR0912, PLR0915
247248

248249
return ret
249250
finally:
250-
logger.setLevel(outer_log_level)
251+
stack.close()
251252

252253
from dvc.repo.open_repo import clean_repos
253254

dvc/logger.py

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55
import logging.handlers
66
import os
77
import sys
8+
from collections.abc import Iterator
9+
from contextlib import contextmanager
810
from typing import ClassVar
911

1012
import colorama
@@ -174,9 +176,19 @@ def _iter_causes(exc):
174176
exc = exc.__cause__
175177

176178

177-
def set_loggers_level(level: int = logging.INFO) -> None:
179+
@contextmanager
180+
def set_loggers_level(level: int = logging.INFO) -> Iterator[None]:
181+
ret: dict[logging.Logger, int] = {}
178182
for name in ["dvc", "dvc_objects", "dvc_data"]:
179-
logging.getLogger(name).setLevel(level)
183+
_logger = logging.getLogger(name)
184+
ret[_logger] = _logger.getEffectiveLevel()
185+
_logger.setLevel(level)
186+
187+
try:
188+
yield
189+
finally:
190+
for _logger, old_lvl in ret.items():
191+
_logger.setLevel(old_lvl)
180192

181193

182194
def setup(level: int = logging.INFO, log_colors: bool = True) -> None:

dvc/repo/experiments/executor/base.py

Lines changed: 19 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,21 @@
1-
import logging
21
import os
32
import pickle
43
import shutil
54
from abc import ABC, abstractmethod
65
from collections.abc import Iterable, Iterator
7-
from contextlib import contextmanager
6+
from contextlib import AbstractContextManager, contextmanager
87
from dataclasses import asdict, dataclass
98
from enum import IntEnum
109
from itertools import chain
1110
from typing import TYPE_CHECKING, Any, Callable, NamedTuple, Optional, Union
1211

12+
from funcy import nullcontext
1313
from scmrepo.exceptions import SCMError
1414

1515
from dvc.env import DVC_EXP_AUTO_PUSH, DVC_EXP_GIT_REMOTE
1616
from dvc.exceptions import DvcException
1717
from dvc.log import logger
18+
from dvc.logger import set_loggers_level
1819
from dvc.repo.experiments.exceptions import ExperimentExistsError
1920
from dvc.repo.experiments.refs import EXEC_BASELINE, EXEC_BRANCH, ExpRefInfo
2021
from dvc.repo.experiments.utils import to_studio_params
@@ -466,8 +467,8 @@ def reproduce(
466467

467468
if queue is not None:
468469
queue.put((rev, os.getpid()))
469-
if log_errors and log_level is not None:
470-
cls._set_log_level(log_level)
470+
471+
log_ctx = cls._set_log_level(log_level) if log_errors else nullcontext()
471472

472473
exp_hash: Optional[str] = None
473474
exp_ref: Optional[ExpRefInfo] = None
@@ -476,14 +477,17 @@ def reproduce(
476477
if info.name:
477478
ui.write(f"Reproducing experiment '{info.name}'")
478479

479-
with cls._repro_dvc(
480-
info,
481-
infofile,
482-
log_errors=log_errors,
483-
copy_paths=copy_paths,
484-
message=message,
485-
**kwargs,
486-
) as dvc:
480+
with (
481+
log_ctx,
482+
cls._repro_dvc(
483+
info,
484+
infofile,
485+
log_errors=log_errors,
486+
copy_paths=copy_paths,
487+
message=message,
488+
**kwargs,
489+
) as dvc,
490+
):
487491
args, kwargs = cls._repro_args(dvc)
488492
if args:
489493
targets: Optional[Union[list, str]] = args[0]
@@ -786,13 +790,10 @@ def _raise_ref_conflict(scm, ref, new_rev):
786790
return orig_rev
787791

788792
@staticmethod
789-
def _set_log_level(level):
790-
# When executor.reproduce is run in a multiprocessing child process,
791-
# dvc.cli.main will not be called for that child process so we need to
792-
# setup logging ourselves
793-
dvc_logger = logging.getLogger("dvc")
793+
def _set_log_level(level: Optional[int]) -> AbstractContextManager[None]:
794794
if level is not None:
795-
dvc_logger.setLevel(level)
795+
return set_loggers_level(level)
796+
return nullcontext()
796797

797798
@staticmethod
798799
def _copy_path(src, dst):

pyproject.toml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -175,7 +175,6 @@ filterwarnings = [
175175
"ignore:unclosed database.*sqlite3.Connection:ResourceWarning",
176176
"ignore:unclosed.*<socket.socket:ResourceWarning",
177177
]
178-
log_level = "debug"
179178
markers = [
180179
"needs_internet: Might need network access for the tests",
181180
"studio: Tests verifying contract between DVC and Studio",

tests/conftest.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import json
22
import os
33
import sys
4-
from contextlib import suppress
4+
from contextlib import ExitStack, suppress
55

66
import pytest
77

@@ -46,10 +46,10 @@ def reset_loglevel(request, caplog):
4646
ini_opt = request.config.getini("log_level")
4747

4848
level = request.config.getoption("--log-level") or ini_opt
49-
if level:
50-
with caplog.at_level(level.upper(), logger="dvc"):
51-
yield
52-
else:
49+
with ExitStack() as stack:
50+
if level:
51+
for name in ["dvc", "dvc_data", "dvc_objects"]:
52+
stack.enter_context(caplog.at_level(level.upper(), logger=name))
5353
yield
5454

5555

tests/func/artifacts/test_artifacts.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
import pytest
66

7+
from dvc import env
78
from dvc.annotations import Artifact
89
from dvc.exceptions import ArtifactNotFoundError, InvalidArgumentError
910
from dvc.repo.artifacts import Artifacts, check_name_format
@@ -283,7 +284,13 @@ def test_artifacts_download_subrepo(tmp_dir, scm, sub):
283284
assert Artifacts.get(".", name, force=True) == result
284285

285286

286-
def test_artifacts_download_studio(tmp_dir, dvc, mocker):
287+
def test_artifacts_download_studio(monkeypatch, tmp_dir, dvc, mocker, tmp_path_factory):
288+
global_config_dir = tmp_path_factory.mktemp("global_config")
289+
monkeypatch.setenv(env.DVC_GLOBAL_CONFIG_DIR, str(global_config_dir))
290+
# reset config to ensure it picks up the new global config
291+
dvc.__dict__.pop("config")
292+
assert dvc.config.files["global"] == os.fspath(global_config_dir / "config")
293+
287294
with dvc.config.edit("global") as conf:
288295
conf["studio"]["token"] = "mytoken"
289296

tests/func/test_run_cache.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -238,9 +238,9 @@ def test_push_pull_unsupported(tmp_dir, dvc, mocker, run_copy, local_remote, cap
238238
mocker.patch.object(
239239
dvc.cloud, "get_remote_odb", side_effect=RunCacheNotSupported("foo")
240240
)
241-
with caplog.at_level(logging.DEBUG):
241+
with caplog.at_level(logging.DEBUG, logger="dvc"):
242242
dvc.push(run_cache=True)
243243
assert "failed to push run cache" in caplog.text
244-
with caplog.at_level(logging.DEBUG):
244+
with caplog.at_level(logging.DEBUG, logger="dvc"):
245245
dvc.pull(run_cache=True)
246246
assert "failed to pull run cache" in caplog.text

tests/integration/test_studio_live_experiments.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ def test_post_to_studio(
2929
monkeypatch.setenv(DVC_STUDIO_REPO_URL, "STUDIO_REPO_URL")
3030
monkeypatch.setenv(DVC_STUDIO_TOKEN, "STUDIO_TOKEN")
3131
monkeypatch.setenv(DVC_STUDIO_URL, "https://0.0.0.0")
32-
monkeypatch.setenv(DVC_STUDIO_OFFLINE, offline)
32+
monkeypatch.setenv(DVC_STUDIO_OFFLINE, str(offline))
3333
if dvc_exp_git_remote:
3434
monkeypatch.setenv(DVC_EXP_GIT_REMOTE, dvc_exp_git_remote)
3535

0 commit comments

Comments
 (0)