Skip to content

Commit 86be2a6

Browse files
committed
Merge remote-tracking branch 'origin/elab_metadata_integration' into develop
2 parents 39f3ce9 + 0d337da commit 86be2a6

File tree

3 files changed

+108
-17
lines changed

3 files changed

+108
-17
lines changed

.cspell/custom-dictionary.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ basepath
2020
bitshift
2121
bysource
2222
calib
23+
caplog
2324
checkscan
2425
clim
2526
codemirror

src/specsanalyzer/logging.py

Lines changed: 21 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -41,28 +41,32 @@ def setup_logging(
4141
# Create base logger
4242
base_logger = logging.getLogger("specsanalyzer")
4343
base_logger.setLevel(logging.DEBUG) # Set the minimum log level for the logger
44-
if set_base_handler or not base_logger.hasHandlers():
45-
if base_logger.hasHandlers():
44+
if set_base_handler or len(base_logger.handlers) == 0:
45+
if len(base_logger.handlers):
4646
base_logger.handlers.clear()
4747

4848
# Determine log file path
4949
if user_log_path is None:
5050
user_log_path = DEFAULT_LOG_DIR
51-
os.makedirs(user_log_path, exist_ok=True)
52-
log_file = os.path.join(user_log_path, f"sed_{datetime.now().strftime('%Y-%m-%d')}.log")
53-
54-
# Create file handler and set level to debug
55-
file_handler = logging.FileHandler(log_file)
56-
file_handler.setLevel(FILE_VERBOSITY)
57-
58-
# Create formatter for file
59-
file_formatter = logging.Formatter(
60-
"%(asctime)s - %(name)s - %(levelname)s - %(message)s in %(filename)s:%(lineno)d",
61-
)
62-
file_handler.setFormatter(file_formatter)
63-
64-
# Add file handler to logger
65-
base_logger.addHandler(file_handler)
51+
try:
52+
os.makedirs(user_log_path, exist_ok=True)
53+
log_file = os.path.join(user_log_path, f"sed_{datetime.now().strftime('%Y-%m-%d')}.log")
54+
55+
# Create file handler and set level to debug
56+
file_handler = logging.FileHandler(log_file)
57+
file_handler.setLevel(FILE_VERBOSITY)
58+
59+
# Create formatter for file
60+
file_formatter = logging.Formatter(
61+
"%(asctime)s - %(name)s - %(levelname)s - %(message)s in %(filename)s:%(lineno)d",
62+
)
63+
file_handler.setFormatter(file_formatter)
64+
65+
# Add file handler to logger
66+
base_logger.addHandler(file_handler)
67+
except PermissionError:
68+
logging.warning(f"Cannot create logfile in Folder {user_log_path}, disabling logfile.")
69+
base_logger.addHandler(logging.NullHandler())
6670

6771
# create named logger
6872
logger = base_logger.getChild(name)

tests/test_logging.py

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
import io
2+
import logging
3+
import os
4+
from datetime import datetime
5+
6+
import pytest
7+
8+
from specsanalyzer.logging import set_verbosity
9+
from specsanalyzer.logging import setup_logging
10+
11+
12+
@pytest.fixture
13+
def logger_():
14+
logger = setup_logging("test_logger")
15+
log_capture_string = io.StringIO()
16+
ch = logging.StreamHandler(log_capture_string)
17+
ch.setLevel(logging.DEBUG)
18+
logger.addHandler(ch)
19+
yield logger, log_capture_string
20+
21+
22+
def test_debug_logging(logger_):
23+
logger, log_capture_string = logger_
24+
logger.debug("This is a debug message")
25+
assert "This is a debug message" in log_capture_string.getvalue()
26+
27+
28+
def test_info_logging(logger_):
29+
logger, log_capture_string = logger_
30+
logger.info("This is an info message")
31+
assert "This is an info message" in log_capture_string.getvalue()
32+
33+
34+
def test_warning_logging(logger_):
35+
logger, log_capture_string = logger_
36+
logger.warning("This is a warning message")
37+
assert "This is a warning message" in log_capture_string.getvalue()
38+
39+
40+
def test_error_logging(logger_):
41+
logger, log_capture_string = logger_
42+
logger.error("This is an error message")
43+
assert "This is an error message" in log_capture_string.getvalue()
44+
45+
46+
def test_critical_logging(logger_):
47+
logger, log_capture_string = logger_
48+
logger.critical("This is a critical message")
49+
assert "This is a critical message" in log_capture_string.getvalue()
50+
51+
52+
def test_set_verbosity(logger_):
53+
logger, log_capture_string = logger_
54+
set_verbosity(logger, verbose=True)
55+
assert logger.handlers[0].level == logging.INFO
56+
set_verbosity(logger, verbose=False)
57+
assert logger.handlers[0].level == logging.WARNING
58+
59+
60+
def test_logger_has_base_logger(logger_):
61+
logger, log_capture_string = logger_
62+
assert logger.name == "specsanalyzer.test_logger"
63+
assert logger.parent.name == "specsanalyzer"
64+
assert logger.parent.parent.name == "root"
65+
assert logger.parent.level == logging.DEBUG
66+
assert isinstance(logger.parent.handlers[0], logging.FileHandler)
67+
68+
69+
def test_logger_creates_logfile(tmp_path):
70+
logger = setup_logging("test_logger", set_base_handler=True, user_log_path=tmp_path)
71+
log_file = os.path.join(tmp_path, f"sed_{datetime.now().strftime('%Y-%m-%d')}.log")
72+
assert os.path.exists(log_file)
73+
with open(log_file) as f:
74+
assert f.read() == ""
75+
logger.debug("This is a debug message")
76+
with open(log_file) as f:
77+
assert "This is a debug message" in f.read()
78+
79+
80+
def test_readonly_path(tmp_path, caplog):
81+
os.chmod(tmp_path, 0o444)
82+
with caplog.at_level(logging.WARNING):
83+
setup_logging("test_logger", set_base_handler=True, user_log_path=tmp_path)
84+
assert f"Cannot create logfile in Folder {tmp_path}, disabling logfile." in caplog.messages[0]
85+
log_file = os.path.join(tmp_path, f"sed_{datetime.now().strftime('%Y-%m-%d')}.log")
86+
assert not os.path.exists(log_file)

0 commit comments

Comments
 (0)