Skip to content

Commit

Permalink
now possible to check also for logger exception types
Browse files Browse the repository at this point in the history
  • Loading branch information
97gamjak committed May 5, 2024
1 parent a0c9ce7 commit 8ab4f60
Show file tree
Hide file tree
Showing 4 changed files with 60 additions and 38 deletions.
18 changes: 11 additions & 7 deletions PQAnalysis/traj/trajectory.py
Original file line number Diff line number Diff line change
Expand Up @@ -184,8 +184,8 @@ def window(
-------
If not all frames are included in the windows, a warning is issued.
Returns
-------
Yields
------
Iterable[Trajectory]
An iterable over the windows of the trajectory with the specified window size and gap.
"""
Expand All @@ -194,28 +194,32 @@ def window(
if window_stop is None:
window_stop = len(self)

# If window_start is less than 0 or greater than the length of the trajectory, raise an IndexError
# If window_start is less than 0 or greater than the
# length of the trajectory, raise an IndexError
if window_start < 0 or window_start > len(self):
self.logger.error(
"start index is less than 0 or greater than the length of the trajectory",
exception=IndexError,
)

# If window_stop is less than 0 or greater than the length of the trajectory, raise an IndexError
# If window_stop is less than 0 or greater than the
# length of the trajectory, raise an IndexError
if window_stop < 0 or window_stop > len(self):
self.logger.error(
"stop index is less than 0 or greater than the length of the trajectory",
exception=IndexError,
)

# If window_step is less than 1 or greater than the length of the trajectory, raise an IndexError
# If window_step is less than 1 or greater than
# the length of the trajectory, raise an IndexError
if window_size < 1 or window_size > len(self):
self.logger.error(
"window size can not be less than 1 or greater than the length of the trajectory",
exception=IndexError,
)

# If window_gap is less than 1 or greater than the length of the trajectory, raise an IndexError
# If window_gap is less than 1 or greater than
# the length of the trajectory, raise an IndexError
if window_gap < 1 or window_gap > len(self):
self.logger.error(
"window gap can not be less than 1 or greater than the length of the trajectory",
Expand Down Expand Up @@ -245,7 +249,7 @@ def window(

# generate the window of the trajectory
for i in range(window_start, window_stop - window_size + 1, window_gap):
yield self[i : i + window_size]
yield self[i: i + window_size]

def __contains__(self, item: AtomicSystem) -> bool:
"""
Expand Down
29 changes: 13 additions & 16 deletions PQAnalysis/utils/custom_logging.py
Original file line number Diff line number Diff line change
Expand Up @@ -107,12 +107,16 @@ def _log(self, # pylint: disable=arguments-differ
if the level is logging.ERROR or logging.CRITICAL and the logger
is not enabled for logging.DEBUG.
"""
self.custom_exception = exception
if exception is not None:
extra = {'custom_exception': exception}
else:
extra = None

self._original_log(
level,
msg,
args,
extra,
**kwargs
)

Expand Down Expand Up @@ -147,6 +151,7 @@ def _original_log(self,
level: Any,
msg: Any,
args: Any,
extra=None,
**kwargs) -> None:
"""
The original _log method of the logging.Logger class.
Expand All @@ -162,22 +167,11 @@ def _original_log(self,
The message to log.
args : Any
The arguments of the log message.
extra : Any, optional
Additional information to log, by default None.
"""

super()._log(level, msg, args, **kwargs)

def makeRecord(self, name, level, fn, lno, msg, args, exc_info,
func=None, extra=None, sinfo=None):
"""
This method creates a log record.
"""

record = super().makeRecord(name, level, fn, lno, msg, args, exc_info,
func=func, extra=extra, sinfo=sinfo)
if hasattr(self, 'custom_exception'):
setattr(record, 'custom_exception', self.custom_exception)

return record
super()._log(level, msg, args, extra=extra, **kwargs)

def error(self,
msg: Any,
Expand Down Expand Up @@ -338,7 +332,10 @@ def format(self, record: logging.LogRecord) -> str:
name = record.name

if hasattr(record, 'custom_exception'):
header = f'{formatted_level} {name} - {record.custom_exception}\n\n'
header = (
f'{formatted_level} {name} - '
f'{record.custom_exception.__qualname__}\n\n'
)
else:
header = f'{formatted_level} {name}\n\n'

Expand Down
30 changes: 25 additions & 5 deletions tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -88,23 +88,43 @@ def caplog_for_logger(caplog, logger_name, level):
logger.removeHandler(caplog.handler)


def assert_logging(caplog, logging_name, logging_level, message_to_test, function, *args, **kwargs):
def assert_logging_with_exception(caplog, logging_name, logging_level, message_to_test, exception, function, *args, **kwargs):
with caplog_for_logger(caplog, __package_name__ + "." + logging_name, logging_level):
result = None
try:
result = function(*args, **kwargs)
except SystemExit:
pass

assert caplog.record_tuples[0][0] == __package_name__ + \
record = caplog.records[0]

assert record.name == __package_name__ + \
"." + logging_name
assert caplog.record_tuples[0][1] == logging.getLevelName(
logging_level)
message = caplog.record_tuples[0][2]
assert record.levelno == logging.getLevelName(
logging_level
)

if exception is not None:
assert record.custom_exception == exception

message = record.msg

messages = [message.strip() for message in message.split("\n")]

for message in messages:
assert message in message_to_test

return result


def assert_logging(caplog, logging_name, logging_level, message_to_test, function, *args, **kwargs):
return assert_logging_with_exception(
caplog,
logging_name,
logging_level,
message_to_test,
None,
function,
*args,
**kwargs
)
21 changes: 11 additions & 10 deletions tests/topology/test_topology.py
Original file line number Diff line number Diff line change
Expand Up @@ -147,17 +147,17 @@ def test_setup_residues(self, caplog):
topology.reference_residues = reference_residues

assert_logging(
caplog,
Topology.__qualname__,
"ERROR",
(
caplog=caplog,
logging_name=Topology.__qualname__,
logging_level="ERROR",
message_to_test=(
"The element of atom 0 is not set. If any reference residues are given the "
"program tries to automatically deduce the residues from the residue ids and "
"the reference residues. This means that any atom with an unknown element "
"raises an error. To avoid deducing residue information please set 'check_residues' "
"to False"
),
topology._setup_residues,
function=topology._setup_residues,
residue_ids=residue_ids,
atoms=atoms
)
Expand All @@ -167,19 +167,20 @@ def test_setup_residues(self, caplog):
topology.reference_residues = reference_residues

residues, new_atoms = assert_logging(
caplog,
Topology.__qualname__,
"WARNING",
(
caplog=caplog,
logging_name=Topology.__qualname__,
logging_level="WARNING",
message_to_test=(
"The element of atom 1 (Element(c, 6, 12.0107)) does not match "
"the element of the reference residue ALA (Element(h, 1, 1.00794)). "
"Therefore the element type of the residue description will be used "
"within the topology format!"
),
topology._setup_residues,
function=topology._setup_residues,
residue_ids=residue_ids,
atoms=atoms,
)

assert len(residues) == 2
assert new_atoms == atoms
assert residues[0] == QMResidue(Element('C'))
Expand Down

0 comments on commit 8ab4f60

Please sign in to comment.