Skip to content

Commit

Permalink
Merge pull request #4906 from jenshnielsen/always_set_config
Browse files Browse the repository at this point in the history
Rework config fixtures
  • Loading branch information
jenshnielsen authored Oct 2, 2023
2 parents 1c76341 + 3d69c69 commit fbea1a3
Show file tree
Hide file tree
Showing 28 changed files with 86 additions and 214 deletions.
4 changes: 2 additions & 2 deletions qcodes/logger/logger.py
Original file line number Diff line number Diff line change
Expand Up @@ -275,7 +275,7 @@ def start_logger() -> None:
logging.getLogger(name).setLevel(level)

root_logger = logging.getLogger()
root_logger.setLevel(logging.DEBUG)
root_logger.setLevel(logging.NOTSET)

# remove previously set handlers
for handler in (console_handler, file_handler, telemetry_handler):
Expand Down Expand Up @@ -484,7 +484,7 @@ class LogCapture:
def __init__(self, logger: logging.Logger = logging.getLogger(),
level: Optional[LevelType] = None) -> None:
self.logger = logger
self.level = level or logging.DEBUG
self.level = level or logging.NOTSET

self.stashed_handlers = copy(self.logger.handlers)
for h in self.stashed_handlers:
Expand Down
75 changes: 1 addition & 74 deletions qcodes/tests/common.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,8 @@
from __future__ import annotations

import copy
import cProfile
import os
import tempfile
from collections.abc import Generator, Mapping, Sequence
from contextlib import contextmanager
from collections.abc import Mapping, Sequence
from functools import wraps
from pathlib import Path
from time import sleep
Expand All @@ -14,10 +11,7 @@
import pytest
from typing_extensions import ParamSpec

import qcodes
from qcodes.configuration import Config, DotDict
from qcodes.metadatable import MetadatableWithName
from qcodes.utils import deprecate

if TYPE_CHECKING:
from pytest import ExceptionInfo
Expand Down Expand Up @@ -179,73 +173,6 @@ def full_name(self) -> str:
return self.full_name


@deprecate(reason="Unused internally", alternative="default_config fixture")
@contextmanager
def default_config(user_config: str | None = None) -> Generator[None, None, None]:
"""
Context manager to temporarily establish default config settings.
This is achieved by overwriting the config paths of the user-,
environment-, and current directory-config files with the path of the
config file in the qcodes repository.
Additionally the current config object `qcodes.config` gets copied and
reestablished.
Args:
user_config: represents the user config file content.
"""
home_file_name = Config.home_file_name
schema_home_file_name = Config.schema_home_file_name
env_file_name = Config.env_file_name
schema_env_file_name = Config.schema_env_file_name
cwd_file_name = Config.cwd_file_name
schema_cwd_file_name = Config.schema_cwd_file_name

Config.home_file_name = ''
with tempfile.TemporaryDirectory() as tmpdirname:
file_name = os.path.join(tmpdirname, 'user_config.json')
file_name_schema = os.path.join(tmpdirname, 'user_config_schema.json')
if user_config is not None:
with open(file_name, 'w') as f:
f.write(user_config)

Config.home_file_name = file_name
Config.schema_home_file_name = file_name_schema
Config.env_file_name = ''
Config.schema_env_file_name = ''
Config.cwd_file_name = ''
Config.schema_cwd_file_name = ''

default_config_obj: DotDict | None = copy.deepcopy(qcodes.config.current_config)
qcodes.config = Config()

try:
yield
finally:
Config.home_file_name = home_file_name
Config.schema_home_file_name = schema_home_file_name
Config.env_file_name = env_file_name
Config.schema_env_file_name = schema_env_file_name
Config.cwd_file_name = cwd_file_name
Config.schema_cwd_file_name = schema_cwd_file_name

qcodes.config.current_config = default_config_obj


@deprecate(reason="Unused internally", alternative="reset_config_on_exit fixture")
@contextmanager
def reset_config_on_exit() -> Generator[None, None, None]:
"""
Context manager to clean any modification of the in memory config on exit
"""
default_config_obj: DotDict | None = copy.deepcopy(qcodes.config.current_config)

try:
yield
finally:
qcodes.config.current_config = default_config_obj


def compare_dictionaries(
dict_1: Mapping[Any, Any],
dict_2: Mapping[Any, Any],
Expand Down
104 changes: 38 additions & 66 deletions qcodes/tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
from qcodes.dataset.descriptions.dependencies import InterDependencies_
from qcodes.dataset.descriptions.param_spec import ParamSpecBase
from qcodes.dataset.experiment_container import Experiment, new_experiment
from qcodes.instrument import Instrument
from qcodes.station import Station

settings.register_profile("ci", deadline=1000)
Expand All @@ -39,30 +40,13 @@ def pytest_runtest_setup(item: pytest.Item) -> None:


@pytest.fixture(scope="session", autouse=True)
def disable_telemetry() -> Generator[None, None, None]:
def default_session_config(
tmpdir_factory: pytest.TempdirFactory,
) -> Generator[None, None, None]:
"""
We do not want the tests to send up telemetric information, so we disable
that with this fixture.
"""

original_state = qc.config.telemetry.enabled

try:
qc.config.telemetry.enabled = False
yield
finally:
qc.config.telemetry.enabled = original_state


@pytest.fixture(scope="function")
def default_config(tmp_path: Path) -> Generator[None, None, None]:
"""
Fixture to temporarily establish default config settings.
This is achieved by overwriting the config paths of the user-,
environment-, and current directory-config files with the path of the
config file in the qcodes repository,
additionally the current config object `qcodes.config` gets copied and
reestablished.
Set the config for the test session to be the default config.
Making sure that that user config does not influence the tests and
that tests cannot write to the user config.
"""
home_file_name = Config.home_file_name
schema_home_file_name = Config.schema_home_file_name
Expand All @@ -71,61 +55,57 @@ def default_config(tmp_path: Path) -> Generator[None, None, None]:
cwd_file_name = Config.cwd_file_name
schema_cwd_file_name = Config.schema_cwd_file_name

old_config: DotDict | None = copy.deepcopy(qc.config.current_config)
qc.config.current_config = copy.deepcopy(qc.config.defaults)

tmp_path = tmpdir_factory.mktemp("qcodes_tests")

file_name = str(tmp_path / "user_config.json")
file_name_schema = str(tmp_path / "user_config_schema.json")

Config.home_file_name = file_name
Config.schema_home_file_name = file_name_schema
Config.env_file_name = ""
Config.schema_env_file_name = ""
Config.cwd_file_name = ""
Config.schema_cwd_file_name = ""
qc.config.home_file_name = file_name
qc.config.schema_home_file_name = file_name_schema
qc.config.env_file_name = ""
qc.config.schema_env_file_name = ""
qc.config.cwd_file_name = ""
qc.config.schema_cwd_file_name = ""

default_config_obj: DotDict | None = copy.deepcopy(qc.config.current_config)
qc.config = Config()
# set any config that we want to be different from the default
# for the test session here
# also set the default db path here
qc.config.telemetry.enabled = False
qc.config.subscription.default_subscribers = []
qc.config.core.db_location = str(tmp_path / "temp.db")

try:
yield
finally:
Config.home_file_name = home_file_name
Config.schema_home_file_name = schema_home_file_name
Config.env_file_name = env_file_name
Config.schema_env_file_name = schema_env_file_name
Config.cwd_file_name = cwd_file_name
Config.schema_cwd_file_name = schema_cwd_file_name

qc.config.current_config = default_config_obj
qc.config.home_file_name = home_file_name
qc.config.schema_home_file_name = schema_home_file_name
qc.config.env_file_name = env_file_name
qc.config.schema_env_file_name = schema_env_file_name
qc.config.cwd_file_name = cwd_file_name
qc.config.schema_cwd_file_name = schema_cwd_file_name

qc.config.current_config = old_config

@pytest.fixture(scope="function")
def reset_config_on_exit() -> Generator[None, None, None]:

@pytest.fixture(scope="function", autouse=True)
def reset_state_on_exit() -> Generator[None, None, None]:
"""
Fixture to clean any modification of the in memory config on exit
Fixture to clean any shared state on exit
Currently this resets the config to the default config,
closes the default station and closes all instruments.
"""
default_config_obj: DotDict | None = copy.deepcopy(qc.config.current_config)

try:
yield
finally:
qc.config.current_config = default_config_obj


@pytest.fixture(scope="session", autouse=True)
def disable_config_subscriber() -> Generator[None, None, None]:
"""
We do not want the tests to send generate subscription events unless specifically
enabled in the test. So disable any default subscriber defined.
"""

original_state = qc.config.subscription.default_subscribers

try:
qc.config.subscription.default_subscribers = []
yield
finally:
qc.config.subscription.default_subscribers = original_state
Instrument.close_all()
Station.default = None


@pytest.fixture(scope="function", name="empty_temp_db")
Expand Down Expand Up @@ -205,11 +185,3 @@ def _make_standalone_parameters_dataset(
)
dataset.mark_completed()
yield dataset


@pytest.fixture(name="set_default_station_to_none")
def _make_set_default_station_to_none():
"""Makes sure that after startup and teardown there is no default station"""
Station.default = None
yield
Station.default = None
2 changes: 1 addition & 1 deletion qcodes/tests/dataset/dond/test_do0d.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
@pytest.mark.usefixtures("plot_close", "experiment")
@pytest.mark.parametrize("period", [None, 1])
@pytest.mark.parametrize("plot", [None, True, False])
@pytest.mark.parametrize("plot_config", [None, True, False])
@pytest.mark.parametrize("plot_config", [True, None, False])
def test_do0d_with_real_parameter(period, plot, plot_config) -> None:
arrayparam = ArraySetPointParam(name="arrayparam")

Expand Down
Loading

0 comments on commit fbea1a3

Please sign in to comment.