From 1446f236d5ca82a0e284917261c4206b1c2e5422 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristian=20Zar=C4=99bski?= Date: Tue, 22 Oct 2024 08:18:54 +0100 Subject: [PATCH 1/7] Use SimvueConfiguration class for offline directory retrieval --- simvue/client.py | 2 +- simvue/config/__init__.py | 2 -- simvue/config/parameters.py | 13 +++++------ simvue/config/user.py | 10 +++++++-- simvue/factory/proxy/offline.py | 5 +++-- simvue/factory/proxy/remote.py | 2 +- simvue/run.py | 6 +++--- simvue/sender.py | 4 ++-- simvue/utilities.py | 38 +++++++++++++++++++++------------ tests/refactor/test_config.py | 19 +++++++++++------ 10 files changed, 62 insertions(+), 39 deletions(-) diff --git a/simvue/client.py b/simvue/client.py index 9710517e..3c86abce 100644 --- a/simvue/client.py +++ b/simvue/client.py @@ -26,7 +26,7 @@ from .simvue_types import DeserializedContent from .utilities import check_extra, prettify_pydantic from .models import FOLDER_REGEX, NAME_REGEX -from .config import SimvueConfiguration +from .config.user import SimvueConfiguration if typing.TYPE_CHECKING: pass diff --git a/simvue/config/__init__.py b/simvue/config/__init__.py index db386d99..28232a84 100644 --- a/simvue/config/__init__.py +++ b/simvue/config/__init__.py @@ -5,5 +5,3 @@ This module contains definitions for the Simvue configuration options """ - -from .user import SimvueConfiguration as SimvueConfiguration diff --git a/simvue/config/parameters.py b/simvue/config/parameters.py index 2edad78e..9b858bf0 100644 --- a/simvue/config/parameters.py +++ b/simvue/config/parameters.py @@ -19,12 +19,6 @@ from simvue.version import __version__ from simvue.api import get -CONFIG_FILE_NAMES: list[str] = ["simvue.toml", ".simvue.toml"] - -CONFIG_INI_FILE_NAMES: list[str] = [ - f'{pathlib.Path.cwd().joinpath("simvue.ini")}', - f'{pathlib.Path.home().joinpath(".simvue.ini")}', -] logger = logging.getLogger(__file__) @@ -77,6 +71,13 @@ def check_valid_server(cls, values: "ServerSpecifications") -> bool: class OfflineSpecifications(pydantic.BaseModel): cache: typing.Optional[pathlib.Path] = None + @pydantic.field_validator("cache") + @classmethod + def cache_to_str(cls, v: typing.Any) -> str: + if not v and not (v := os.environ.get("SIMVUE_OFFLINE_DIRECTORY")): + return v + return f"{v}" + class DefaultRunSpecifications(pydantic.BaseModel): name: typing.Optional[str] = None diff --git a/simvue/config/user.py b/simvue/config/user.py index e3225fc9..9b39b54a 100644 --- a/simvue/config/user.py +++ b/simvue/config/user.py @@ -20,14 +20,17 @@ import simvue.utilities as sv_util from simvue.config.parameters import ( - CONFIG_FILE_NAMES, - CONFIG_INI_FILE_NAMES, ClientGeneralOptions, DefaultRunSpecifications, ServerSpecifications, OfflineSpecifications, ) +from simvue.config.files import ( + CONFIG_FILE_NAMES, + CONFIG_INI_FILE_NAMES, +) + logger = logging.getLogger(__name__) @@ -61,6 +64,8 @@ def _parse_ini_config(cls, ini_file: pathlib.Path) -> dict[str, dict[str, str]]: config_dict["server"]["token"] = token if url := parser.get("server", "url"): config_dict["server"]["url"] = url + if offline_dir := parser.get("offline", "cache"): + config_dict["offline"]["cache"] = offline_dir return config_dict @@ -88,6 +93,7 @@ def fetch( logger.warning("No config file found, checking environment variables") _config_dict["server"] = _config_dict.get("server", {}) + _config_dict["offline"] = _config_dict.get("offline", {}) # Ranking of configurations for token and URl is: # Envionment Variables > Run Definition > Configuration File diff --git a/simvue/factory/proxy/offline.py b/simvue/factory/proxy/offline.py index 1e6583d9..cda666c7 100644 --- a/simvue/factory/proxy/offline.py +++ b/simvue/factory/proxy/offline.py @@ -9,9 +9,9 @@ import randomname from simvue.factory.proxy.base import SimvueBaseClass +from simvue.config.user import SimvueConfiguration from simvue.utilities import ( create_file, - get_offline_directory, prepare_for_api, skip_if_failed, ) @@ -32,7 +32,8 @@ def __init__( ) -> None: super().__init__(name, uniq_id, suppress_errors) - self._directory: str = os.path.join(get_offline_directory(), self._uuid) + _offline_dir = SimvueConfiguration.fetch().offline.cache + self._directory: str = os.path.join(_offline_dir, self._uuid) os.makedirs(self._directory, exist_ok=True) diff --git a/simvue/factory/proxy/remote.py b/simvue/factory/proxy/remote.py index f61ed0d3..3c8fdba4 100644 --- a/simvue/factory/proxy/remote.py +++ b/simvue/factory/proxy/remote.py @@ -3,7 +3,7 @@ import http if typing.TYPE_CHECKING: - from simvue.config import SimvueConfiguration + from simvue.config.user import SimvueConfiguration from simvue.api import get, post, put from simvue.factory.proxy.base import SimvueBaseClass diff --git a/simvue/run.py b/simvue/run.py index 12b1fbd7..5670c093 100644 --- a/simvue/run.py +++ b/simvue/run.py @@ -32,7 +32,7 @@ import psutil from pydantic import ValidationError -from .config import SimvueConfiguration +from .config.user import SimvueConfiguration import simvue.api as sv_api from .factory.dispatch import Dispatcher @@ -48,7 +48,6 @@ calculate_sha256, compare_alerts, skip_if_failed, - get_offline_directory, validate_timestamp, simvue_timestamp, ) @@ -405,7 +404,8 @@ def _offline_dispatch_callback( run_id: typing.Optional[str] = self._id, uuid: str = self._uuid, ) -> None: - if not os.path.exists((_offline_directory := get_offline_directory())): + _offline_directory = self.config.offline.cache + if not os.path.exists(_offline_directory): logger.error( f"Cannot write to offline directory '{_offline_directory}', directory not found." ) diff --git a/simvue/sender.py b/simvue/sender.py index 83290748..264a183c 100644 --- a/simvue/sender.py +++ b/simvue/sender.py @@ -12,7 +12,7 @@ from simvue.config.user import SimvueConfiguration from .factory.proxy.remote import Remote -from .utilities import create_file, get_offline_directory, remove_file +from .utilities import create_file, remove_file logger = logging.getLogger(__name__) @@ -88,7 +88,7 @@ def sender() -> str: """ Asynchronous upload of runs to Simvue server """ - directory = get_offline_directory() + directory = SimvueConfiguration.fetch().offline.cache # Clean up old runs after waiting 5 mins runs = glob.glob(f"{directory}/*/sent") diff --git a/simvue/utilities.py b/simvue/utilities.py index 6270a2d4..0105e8ac 100644 --- a/simvue/utilities.py +++ b/simvue/utilities.py @@ -16,6 +16,9 @@ from datetime import timezone +import toml +from simvue.config.files import CONFIG_FILE_NAMES, CONFIG_INI_FILE_NAMES + CHECKSUM_BLOCK_SIZE = 4096 EXTRAS: tuple[str, ...] = ("plot", "torch") @@ -260,24 +263,31 @@ def get_offline_directory() -> str: """ Get directory for offline cache """ - directory = None + _directory: typing.Optional[str] = None + + _config_file: typing.Optional[pathlib.Path] = find_first_instance_of_file( + CONFIG_FILE_NAMES, check_user_space=True + ) + _config_file_ini: typing.Optional[pathlib.Path] = None - for filename in ( - os.path.join(os.path.expanduser("~"), ".simvue.ini"), - "simvue.ini", - ): - if not filename or not os.path.exists(filename): - continue + if _config_file: + _config = toml.load(_config_file) + _directory = _config.get("offline", {}).get("cache") + + if not _config_file: + _config_file_ini: typing.Optional[pathlib.Path] = find_first_instance_of_file( + CONFIG_INI_FILE_NAMES, check_user_space=True + ) - with contextlib.suppress(Exception): - config = configparser.ConfigParser() - config.read(filename) - directory = config.get("offline", "cache") + if _config_file_ini and not _directory: + _config_ini = configparser.ConfigParser() + _config_ini.read(_config_file_ini) + _directory = _config_ini.get("offline", "cache") - if not (directory := os.environ.get("SIMVUE_OFFLINE_DIRECTORY", directory)): - directory = os.path.join(os.path.expanduser("~"), ".simvue") + if not (_directory := os.environ.get("SIMVUE_OFFLINE_DIRECTORY", _directory)): + _directory = os.path.join(os.path.expanduser("~"), ".simvue") - return directory + return _directory def create_file(filename: str) -> None: diff --git a/tests/refactor/test_config.py b/tests/refactor/test_config.py index f7236a1d..b9c623c2 100644 --- a/tests/refactor/test_config.py +++ b/tests/refactor/test_config.py @@ -5,7 +5,7 @@ import pathlib import pytest_mock import tempfile -from simvue.config import SimvueConfiguration +from simvue.config.user import SimvueConfiguration @pytest.mark.config @@ -57,12 +57,18 @@ def test_config_setup( [server] url = "{_url}" token = "{_token}" + +[offline] +cache = "{temp_d}" """ else: _lines = f""" [server] url = {_url} token = {_token} + +[offline] +cache = {temp_d} """ if use_file == "extended": @@ -78,19 +84,19 @@ def test_config_setup( mocker.patch("simvue.config.parameters.get_expiry", lambda *_, **__: 1e10) mocker.patch("simvue.config.user.sv_util.find_first_instance_of_file", lambda *_, **__: _config_file) - import simvue.config + import simvue.config.user if not use_file and not use_env and not use_args: with pytest.raises(RuntimeError): - simvue.config.SimvueConfiguration.fetch() + simvue.config.user.SimvueConfiguration.fetch() return elif use_args: - _config = simvue.config.SimvueConfiguration.fetch( + _config = simvue.config.user.SimvueConfiguration.fetch( server_url=_arg_url, server_token=_arg_token ) else: - _config = simvue.config.SimvueConfiguration.fetch() + _config = simvue.config.user.SimvueConfiguration.fetch() if use_file: assert _config.config_file() == _config_file @@ -104,6 +110,7 @@ def test_config_setup( elif use_file: assert _config.server.url == _url assert _config.server.token == _token + assert _config.offline.cache == temp_d if use_file == "extended": assert _config.run.description == _description @@ -114,5 +121,5 @@ def test_config_setup( assert not _config.run.description assert not _config.run.tags - simvue.config.SimvueConfiguration.config_file.cache_clear() + simvue.config.user.SimvueConfiguration.config_file.cache_clear() From 85e75d94088fc805b121f8075b4e213e83f4006b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristian=20Zar=C4=99bski?= Date: Tue, 22 Oct 2024 09:23:27 +0100 Subject: [PATCH 2/7] Fix tests and remove get_offline_directory --- simvue/config/files.py | 16 +++++++++++++++ simvue/config/user.py | 2 +- simvue/utilities.py | 34 -------------------------------- tests/refactor/conftest.py | 12 +++++------ tests/refactor/test_config.py | 2 +- tests/refactor/test_run_class.py | 1 + 6 files changed, 25 insertions(+), 42 deletions(-) create mode 100644 simvue/config/files.py diff --git a/simvue/config/files.py b/simvue/config/files.py new file mode 100644 index 00000000..0476e9d2 --- /dev/null +++ b/simvue/config/files.py @@ -0,0 +1,16 @@ +""" +Simvue Config File Lists +======================== + +Contains lists of valid Simvue configuration file names. + +""" + +import pathlib + +CONFIG_FILE_NAMES: list[str] = ["simvue.toml", ".simvue.toml"] + +CONFIG_INI_FILE_NAMES: list[str] = [ + f'{pathlib.Path.cwd().joinpath("simvue.ini")}', + f'{pathlib.Path.home().joinpath(".simvue.ini")}', +] diff --git a/simvue/config/user.py b/simvue/config/user.py index 9b39b54a..0d9a2ec8 100644 --- a/simvue/config/user.py +++ b/simvue/config/user.py @@ -55,7 +55,7 @@ def _parse_ini_config(cls, ini_file: pathlib.Path) -> dict[str, dict[str, str]]: stacklevel=2, ) - config_dict: dict[str, dict[str, str]] = {"server": {}} + config_dict: dict[str, dict[str, str]] = {"server": {}, "offline": {}} with contextlib.suppress(Exception): parser = configparser.ConfigParser() diff --git a/simvue/utilities.py b/simvue/utilities.py index 0105e8ac..74a2eb8b 100644 --- a/simvue/utilities.py +++ b/simvue/utilities.py @@ -1,4 +1,3 @@ -import configparser import datetime import hashlib import logging @@ -16,8 +15,6 @@ from datetime import timezone -import toml -from simvue.config.files import CONFIG_FILE_NAMES, CONFIG_INI_FILE_NAMES CHECKSUM_BLOCK_SIZE = 4096 EXTRAS: tuple[str, ...] = ("plot", "torch") @@ -259,37 +256,6 @@ def wrapper(self, *args, **kwargs) -> typing.Any: return wrapper -def get_offline_directory() -> str: - """ - Get directory for offline cache - """ - _directory: typing.Optional[str] = None - - _config_file: typing.Optional[pathlib.Path] = find_first_instance_of_file( - CONFIG_FILE_NAMES, check_user_space=True - ) - _config_file_ini: typing.Optional[pathlib.Path] = None - - if _config_file: - _config = toml.load(_config_file) - _directory = _config.get("offline", {}).get("cache") - - if not _config_file: - _config_file_ini: typing.Optional[pathlib.Path] = find_first_instance_of_file( - CONFIG_INI_FILE_NAMES, check_user_space=True - ) - - if _config_file_ini and not _directory: - _config_ini = configparser.ConfigParser() - _config_ini.read(_config_file_ini) - _directory = _config_ini.get("offline", "cache") - - if not (_directory := os.environ.get("SIMVUE_OFFLINE_DIRECTORY", _directory)): - _directory = os.path.join(os.path.expanduser("~"), ".simvue") - - return _directory - - def create_file(filename: str) -> None: """ Create an empty file diff --git a/tests/refactor/conftest.py b/tests/refactor/conftest.py index 61214b10..f2f599b4 100644 --- a/tests/refactor/conftest.py +++ b/tests/refactor/conftest.py @@ -17,11 +17,11 @@ def __init__(self, level=logging.DEBUG): super().__init__(level) self.counts = [] self.captures = [] - + def emit(self, record): if len(self.captures) != len(self.counts): self.counts = [0] * len(self.captures) - + for i, capture in enumerate(self.captures): if capture in record.msg: self.counts[i] += 1 @@ -48,9 +48,9 @@ def create_test_run(request) -> typing.Generator[typing.Tuple[sv_run.Run, dict], @pytest.fixture -def create_test_run_offline(mocker: pytest_mock.MockerFixture, request) -> typing.Generator[typing.Tuple[sv_run.Run, dict], None, None]: +def create_test_run_offline(mocker: pytest_mock.MockerFixture, request, monkeypatch: pytest.MonkeyPatch) -> typing.Generator[typing.Tuple[sv_run.Run, dict], None, None]: with tempfile.TemporaryDirectory() as temp_d: - mocker.patch.object(simvue.utilities, "get_offline_directory", lambda *_: temp_d) + monkeypatch.setenv("SIMVUE_OFFLINE_DIRECTORY", temp_d) with sv_run.Run("offline") as run: yield run, setup_test_run(run, True, request) @@ -62,9 +62,9 @@ def create_plain_run(request) -> typing.Generator[typing.Tuple[sv_run.Run, dict] @pytest.fixture -def create_plain_run_offline(mocker: pytest_mock.MockerFixture, request) -> typing.Generator[typing.Tuple[sv_run.Run, dict], None, None]: +def create_plain_run_offline(mocker: pytest_mock.MockerFixture, request, monkeypatch: pytest.MonkeyPatch) -> typing.Generator[typing.Tuple[sv_run.Run, dict], None, None]: with tempfile.TemporaryDirectory() as temp_d: - mocker.patch.object(simvue.utilities, "get_offline_directory", lambda *_: temp_d) + monkeypatch.setenv("SIMVUE_OFFLINE_DIRECTORY", temp_d) with sv_run.Run("offline") as run: yield run, setup_test_run(run, False, request) diff --git a/tests/refactor/test_config.py b/tests/refactor/test_config.py index b9c623c2..362c0e78 100644 --- a/tests/refactor/test_config.py +++ b/tests/refactor/test_config.py @@ -39,7 +39,7 @@ def test_config_setup( _tags: list[str] = ["tag-test", "other-tag"] # Deactivate the server checks for this test - monkeypatch.setenv("SIMVUE_NO_SERVER_CHECK", True) + monkeypatch.setenv("SIMVUE_NO_SERVER_CHECK", "True") if use_env: monkeypatch.setenv("SIMVUE_TOKEN", _other_token) diff --git a/tests/refactor/test_run_class.py b/tests/refactor/test_run_class.py index 1af7cc5e..b8ba4908 100644 --- a/tests/refactor/test_run_class.py +++ b/tests/refactor/test_run_class.py @@ -351,6 +351,7 @@ def test_bad_run_arguments() -> None: run.init("sdas", [34]) +@pytest.mark.run def test_set_folder_details(request: pytest.FixtureRequest) -> None: with sv_run.Run() as run: folder_name: str = "/simvue_unit_tests" From 2e383f5b4096e8e5581d6fed9f8f4929f21023af Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristian=20Zar=C4=99bski?= Date: Tue, 22 Oct 2024 10:20:57 +0100 Subject: [PATCH 3/7] Fix re-validation whenever config object is called --- simvue/config/user.py | 1 + 1 file changed, 1 insertion(+) diff --git a/simvue/config/user.py b/simvue/config/user.py index 0d9a2ec8..4b07f4f2 100644 --- a/simvue/config/user.py +++ b/simvue/config/user.py @@ -71,6 +71,7 @@ def _parse_ini_config(cls, ini_file: pathlib.Path) -> dict[str, dict[str, str]]: @classmethod @sv_util.prettify_pydantic + @functools.lru_cache def fetch( cls, server_url: typing.Optional[str] = None, From ed4dc599ffa5a108cd752ffef2c1be163bb85783 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristian=20Zar=C4=99bski?= Date: Tue, 22 Oct 2024 10:49:21 +0100 Subject: [PATCH 4/7] Allow SIMVUE_OFFLINE_DIRECTORY to override config file --- simvue/config/files.py | 2 ++ simvue/config/parameters.py | 2 -- simvue/config/user.py | 10 ++++++++++ 3 files changed, 12 insertions(+), 2 deletions(-) diff --git a/simvue/config/files.py b/simvue/config/files.py index 0476e9d2..baa80c2f 100644 --- a/simvue/config/files.py +++ b/simvue/config/files.py @@ -14,3 +14,5 @@ f'{pathlib.Path.cwd().joinpath("simvue.ini")}', f'{pathlib.Path.home().joinpath(".simvue.ini")}', ] + +DEFAULT_OFFLINE_DIRECTORY: str = f"{pathlib.Path.home().joinpath('.simvue')}" diff --git a/simvue/config/parameters.py b/simvue/config/parameters.py index 9b858bf0..93a17a89 100644 --- a/simvue/config/parameters.py +++ b/simvue/config/parameters.py @@ -74,8 +74,6 @@ class OfflineSpecifications(pydantic.BaseModel): @pydantic.field_validator("cache") @classmethod def cache_to_str(cls, v: typing.Any) -> str: - if not v and not (v := os.environ.get("SIMVUE_OFFLINE_DIRECTORY")): - return v return f"{v}" diff --git a/simvue/config/user.py b/simvue/config/user.py index 4b07f4f2..4d6d5b4f 100644 --- a/simvue/config/user.py +++ b/simvue/config/user.py @@ -29,6 +29,7 @@ from simvue.config.files import ( CONFIG_FILE_NAMES, CONFIG_INI_FILE_NAMES, + DEFAULT_OFFLINE_DIRECTORY, ) logger = logging.getLogger(__name__) @@ -94,8 +95,17 @@ def fetch( logger.warning("No config file found, checking environment variables") _config_dict["server"] = _config_dict.get("server", {}) + _config_dict["offline"] = _config_dict.get("offline", {}) + # Allow override of specification of offline directory via environment variable + if not (_default_dir := os.environ.get("SIMVUE_OFFLINE_DIRECTORY")): + _default_dir = _config_dict["offline"].get( + "cache", DEFAULT_OFFLINE_DIRECTORY + ) + + _config_dict["offline"]["cache"] = _default_dir + # Ranking of configurations for token and URl is: # Envionment Variables > Run Definition > Configuration File From 284ab871cf951721b567052421456d34b05bdb96 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristian=20Zar=C4=99bski?= Date: Tue, 22 Oct 2024 10:58:52 +0100 Subject: [PATCH 5/7] Added docstrings --- simvue/config/user.py | 20 ++++++++++++++++++++ tests/refactor/test_config.py | 5 ++--- 2 files changed, 22 insertions(+), 3 deletions(-) diff --git a/simvue/config/user.py b/simvue/config/user.py index 4d6d5b4f..85277fa6 100644 --- a/simvue/config/user.py +++ b/simvue/config/user.py @@ -78,6 +78,25 @@ def fetch( server_url: typing.Optional[str] = None, server_token: typing.Optional[str] = None, ) -> "SimvueConfiguration": + """Retrieve the Simvue configuration from this project + + Will retrieve the configuration options set for this project either using + local or global configurations. This function is cached to prevent re-check + of the same files, note this means mid-run changes will not be verified. + + Parameters + ---------- + server_url : str, optional + override the URL used for this session + server_token : str, optional + override the token used for this session + + Return + ------ + SimvueConfiguration + object containing configurations + + """ _config_dict: dict[str, dict[str, str]] = {} try: @@ -131,6 +150,7 @@ def fetch( @classmethod @functools.lru_cache def config_file(cls) -> pathlib.Path: + """Returns the path of top level configuration file used for the session""" _config_file: typing.Optional[pathlib.Path] = ( sv_util.find_first_instance_of_file( CONFIG_FILE_NAMES, check_user_space=True diff --git a/tests/refactor/test_config.py b/tests/refactor/test_config.py index 362c0e78..4bc0cb4e 100644 --- a/tests/refactor/test_config.py +++ b/tests/refactor/test_config.py @@ -40,13 +40,12 @@ def test_config_setup( # Deactivate the server checks for this test monkeypatch.setenv("SIMVUE_NO_SERVER_CHECK", "True") + monkeypatch.delenv("SIMVUE_TOKEN", False) + monkeypatch.delenv("SIMVUE_URL", False) if use_env: monkeypatch.setenv("SIMVUE_TOKEN", _other_token) monkeypatch.setenv("SIMVUE_URL", _other_url) - else: - monkeypatch.delenv("SIMVUE_TOKEN", False) - monkeypatch.delenv("SIMVUE_URL", False) with tempfile.TemporaryDirectory() as temp_d: _config_file = None From ed0b931eb3c2a66bf8d9e893c36d34e93886ce7e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristian=20Zar=C4=99bski?= Date: Tue, 22 Oct 2024 11:18:15 +0100 Subject: [PATCH 6/7] Try owning caching simvue URL checking --- simvue/config/parameters.py | 2 ++ simvue/config/user.py | 4 +--- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/simvue/config/parameters.py b/simvue/config/parameters.py index 93a17a89..b3be337f 100644 --- a/simvue/config/parameters.py +++ b/simvue/config/parameters.py @@ -13,6 +13,7 @@ import typing import pathlib import http +import functools import simvue.models as sv_models from simvue.utilities import get_expiry @@ -43,6 +44,7 @@ def check_token(cls, v: typing.Any) -> str: @pydantic.model_validator(mode="after") @classmethod + @functools.lru_cache def check_valid_server(cls, values: "ServerSpecifications") -> bool: if os.environ.get("SIMVUE_NO_SERVER_CHECK"): return values diff --git a/simvue/config/user.py b/simvue/config/user.py index 85277fa6..77b97aa6 100644 --- a/simvue/config/user.py +++ b/simvue/config/user.py @@ -72,7 +72,6 @@ def _parse_ini_config(cls, ini_file: pathlib.Path) -> dict[str, dict[str, str]]: @classmethod @sv_util.prettify_pydantic - @functools.lru_cache def fetch( cls, server_url: typing.Optional[str] = None, @@ -81,8 +80,7 @@ def fetch( """Retrieve the Simvue configuration from this project Will retrieve the configuration options set for this project either using - local or global configurations. This function is cached to prevent re-check - of the same files, note this means mid-run changes will not be verified. + local or global configurations. Parameters ---------- From 6944e916a6ed488f0a20ceff69e13396b4ad68bb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristian=20Zar=C4=99bski?= Date: Tue, 22 Oct 2024 11:29:07 +0100 Subject: [PATCH 7/7] Only cache URL check --- simvue/config/parameters.py | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/simvue/config/parameters.py b/simvue/config/parameters.py index b3be337f..a0c13b70 100644 --- a/simvue/config/parameters.py +++ b/simvue/config/parameters.py @@ -42,19 +42,15 @@ def check_token(cls, v: typing.Any) -> str: raise AssertionError("Simvue token has expired") return value - @pydantic.model_validator(mode="after") @classmethod @functools.lru_cache - def check_valid_server(cls, values: "ServerSpecifications") -> bool: - if os.environ.get("SIMVUE_NO_SERVER_CHECK"): - return values - + def _check_server(cls, token: str, url: str) -> None: headers: dict[str, str] = { - "Authorization": f"Bearer {values.token}", + "Authorization": f"Bearer {token}", "User-Agent": f"Simvue Python client {__version__}", } try: - response = get(f"{values.url}/api/version", headers) + response = get(f"{url}/api/version", headers) if response.status_code != http.HTTPStatus.OK or not response.json().get( "version" @@ -67,6 +63,14 @@ def check_valid_server(cls, values: "ServerSpecifications") -> bool: except Exception as err: raise AssertionError(f"Exception retrieving server version: {str(err)}") + @pydantic.model_validator(mode="after") + @classmethod + def check_valid_server(cls, values: "ServerSpecifications") -> bool: + if os.environ.get("SIMVUE_NO_SERVER_CHECK"): + return values + + cls._check_server(values.token, values.url) + return values