Skip to content

Commit

Permalink
Pcvl 761 rework test for Logger, LoggerConfig & TokenProvider (#439)
Browse files Browse the repository at this point in the history
  • Loading branch information
MarionQuandela authored Jul 30, 2024
1 parent 95912f1 commit 336c466
Show file tree
Hide file tree
Showing 8 changed files with 164 additions and 80 deletions.
32 changes: 20 additions & 12 deletions perceval/runtime/_token_management.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@
import os
import warnings

from typing import Union

from ..utils import PersistentData, FileFormat

_TOKEN_FILE_NAME = "token"
Expand All @@ -52,37 +54,45 @@ def __init__(self, env_var: str = "PCVL_CLOUD_TOKEN"):
:param file_path: Path to search for a file containing a token (default None)
"""
self._env_var = env_var
self._persistent_data = PersistentData()

def _from_environment_variable(self) -> str:
def _from_environment_variable(self) -> Union[str, None]:
if not self._env_var:
return None
TokenProvider._CACHED_TOKEN = os.getenv(self._env_var)
return TokenProvider._CACHED_TOKEN

def _from_file(self) -> str:
def _from_file(self) -> Union[str, None]:
token = None
persistent_data = PersistentData()
if persistent_data.has_file(_TOKEN_FILE_NAME):
if self._persistent_data.has_file(_TOKEN_FILE_NAME):
try:
token = persistent_data.read_file(_TOKEN_FILE_NAME, FileFormat.TEXT)
token = self._persistent_data.read_file(_TOKEN_FILE_NAME, FileFormat.TEXT)
except OSError:
warnings.warn("Cannot read token persistent file")
return token

def get_token(self) -> str:
def get_token(self) -> Union[str, None]:
"""Search for a token to provide
:return: A token, or None if no token was found
"""
return TokenProvider._CACHED_TOKEN or self._from_environment_variable() or self._from_file()

def save_token(self):
"""Save the current cache token
"""
if self._persistent_data.is_writable():
self._persistent_data.write_file(_TOKEN_FILE_NAME, TokenProvider._CACHED_TOKEN, FileFormat.TEXT)
else:
warnings.warn(UserWarning("Can't save token"))

@staticmethod
def clear_cache():
"""Clear the cached token"""
TokenProvider._CACHED_TOKEN = None

@property
def cache(self) -> str:
def cache(self) -> Union[str, None]:
return TokenProvider._CACHED_TOKEN

@staticmethod
Expand All @@ -96,8 +106,6 @@ def save_token(token: str):
:param token: token to save
"""
persistent_data = PersistentData()
if persistent_data.is_writable():
persistent_data.write_file(_TOKEN_FILE_NAME, token, FileFormat.TEXT)
else:
warnings.warn(UserWarning("Can't save token"))
token_provider = TokenProvider()
token_provider.force_token(token)
token_provider.save_token()
7 changes: 3 additions & 4 deletions perceval/utils/logging/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ class LoggerConfig(dict):
def __init__(self):
super().__init__()
self.reset()
self._persistent_data = PersistentData()
self._load_from_persistent_data()

def _init_channel(self, channel: exqalibur_logging.channel, level: exqalibur_logging.level = exqalibur_logging.level.off):
Expand All @@ -57,8 +58,7 @@ def reset(self):
self._init_channel(exqalibur_logging.channel.user, exqalibur_logging.level.warn)

def _load_from_persistent_data(self):
persistent_data = PersistentData()
config = persistent_data.load_config()
config = self._persistent_data.load_config()
try:
if config and _LOGGING in config:
config = config[_LOGGING]
Expand All @@ -81,5 +81,4 @@ def disable_file(self):
self[_ENABLE_FILE] = False

def save(self):
persistent_data = PersistentData()
persistent_data.save_config({_LOGGING: dict(self)})
self._persistent_data.save_config({_LOGGING: dict(self)})
17 changes: 9 additions & 8 deletions perceval/utils/logging/loggers.py
Original file line number Diff line number Diff line change
Expand Up @@ -76,25 +76,26 @@ def critical(self, msg: str, channel: exq_log.channel = DEFAULT_CHANNEL, exc_inf
class ExqaliburLogger(ILogger):
def initialize(self):
persistent_data = PersistentData()
log_path = self.get_log_file_path()
if persistent_data.is_writable():
exq_log.initialize(log_path)
exq_log.initialize(self.get_log_file_path())
else:
exq_log.initialize()

config = LoggerConfig()
if _ENABLE_FILE in config and config[_ENABLE_FILE]:
print(f"starting to write logs in {log_path}")
self._config = LoggerConfig()
self._configure_logger()

def _configure_logger(self):
if _ENABLE_FILE in self._config and self._config[_ENABLE_FILE]:
print(f"starting to write logs in {self.get_log_file_path()}")
exq_log.enable_file()
else:
exq_log.disable_file()

exq_log.enable_console()

if _CHANNELS in config:
if _CHANNELS in self._config:
channels = list(exq_log.channel.__members__)
levels = list(exq_log.level.__members__)
for channel, level in config[_CHANNELS].items():
for channel, level in self._config[_CHANNELS].items():
level = level['level']
if channel not in channels:
warnings.warn(UserWarning(f"Unknown channel {channel}"))
Expand Down
89 changes: 89 additions & 0 deletions tests/_mock_persistent_data.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
# MIT License
#
# Copyright (c) 2022 Quandela
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.
#
# As a special exception, the copyright holders of exqalibur library give you
# permission to combine exqalibur with code included in the standard release of
# Perceval under the MIT license (or modified versions of such code). You may
# copy and distribute such a combined system following the terms of the MIT
# license for both exqalibur and Perceval. This exception for the usage of
# exqalibur is limited to the python bindings used by Perceval.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.

import os
import uuid
import tempfile

from perceval.utils import PersistentData, LoggerConfig
from perceval.utils.logging import ExqaliburLogger
from perceval.runtime._token_management import TokenProvider

UNIQUE_PART = uuid.uuid4()


class PersistentDataForTests(PersistentData):
"""
Overrides the directory used for persistent data to target a temporary sub-folder.
This allows to run tests without removing actual persistent data or risking messing up system or user directories
"""

def __init__(self):
super().__init__()
self._directory = os.path.join(tempfile.gettempdir(), f'perceval-container-{UNIQUE_PART}', 'perceval-quandela')
try:
self._create_directory()
except OSError:
pass


class TokenProviderForTest(TokenProvider):
"""
Overrides the file used for token to target a file in temporary sub-folder.
This allows to run tests without removing actual persistent data or risking messing up system or user directories
"""

def __init__(self, env_var: str = "PCVL_CLOUD_TOKEN"):
super().__init__(env_var)
self._persistent_data = PersistentDataForTests()


class LoggerConfigForTest(LoggerConfig):
"""
Overrides the file used for logger config to target a file in temporary sub-folder.
This allows to run tests without removing actual persistent data or risking messing up system or user directories
"""

def __init__(self):
super().__init__()
self.reset()
self._persistent_data = PersistentDataForTests()
self._load_from_persistent_data()


class ExqaliburLoggerForTest(ExqaliburLogger):
"""
Overrides the config used for logger .
This allows to run tests without removing actual persistent data or risking messing up system or user directories
"""

def __init__(self) -> None:
super().__init__()
self._config = LoggerConfigForTest()
self._configure_logger()
23 changes: 1 addition & 22 deletions tests/_test_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,18 +27,15 @@
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.

import os
import re
import uuid
import math
import tempfile
from typing import Type
from pathlib import Path

import pytest

import perceval as pcvl
from perceval.utils import StateVector, SVDistribution, PersistentData
from perceval.utils import StateVector, SVDistribution
from perceval.rendering import Format
from perceval.rendering.circuit import ASkin, PhysSkin
from perceval.algorithm import AProcessTomography
Expand Down Expand Up @@ -222,21 +219,3 @@ def _save_or_check(c, tmp_path, circuit_name, save_figs, recursive=False, compac
assert_sv_close(sv4, sv1)
except AssertionError:
print("detected sv are different")


UNIQUE_PART = uuid.uuid4()


class PersistentDataForTests(PersistentData):
"""
Overrides the directory used for persistent data to target a temporary sub-folder.
This allows to run tests without removing actual persistent data or risking messing up system or user directories
"""

def __init__(self):
super().__init__()
self._directory = os.path.join(tempfile.gettempdir(), f'perceval-container-{UNIQUE_PART}', 'perceval-quandela')
try:
os.makedirs(self._directory, exist_ok=True)
except OSError:
pass
11 changes: 6 additions & 5 deletions tests/test_log.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,15 +31,16 @@
import time

import perceval as pcvl
from perceval import logger

from _mock_persistent_data import LoggerConfigForTest, PersistentDataForTests


def test_logger_config():
logger_config = pcvl.LoggerConfig()
logger_config = LoggerConfigForTest()
logger_config.reset()
logger_config.save()

config = pcvl.utils.PersistentData().load_config()
config = logger_config._persistent_data.load_config()
assert config["logging"] == {'use_python_logger': False, 'enable_file': False,
'channels': {'general': {'level': 'off'}, 'resources': {'level': 'off'}, 'user': {'level': 'warn'}}}

Expand All @@ -49,13 +50,13 @@ def test_logger_config():
logger_config.set_level(pcvl.logging.level.warn, pcvl.logging.channel.user)
logger_config.save()

config = pcvl.utils.PersistentData().load_config()
config = logger_config._persistent_data.load_config()
assert config["logging"] == {'use_python_logger': False, 'enable_file': True,
'channels': {'general': {'level': 'warn'}, 'resources': {'level': 'warn'}, 'user': {'level': 'warn'}}}

logger_config.reset()
logger_config.save()

config = pcvl.utils.PersistentData().load_config()
config = logger_config._persistent_data.load_config()
assert config["logging"] == {'use_python_logger': False, 'enable_file': False,
'channels': {'general': {'level': 'off'}, 'resources': {'level': 'off'}, 'user': {'level': 'warn'}}}
2 changes: 1 addition & 1 deletion tests/test_persistent_data.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@

from perceval.utils import PersistentData, FileFormat

from _test_utils import PersistentDataForTests
from _mock_persistent_data import PersistentDataForTests


def test_directory():
Expand Down
Loading

0 comments on commit 336c466

Please sign in to comment.