Source code for armi.utils.customExceptions

# Copyright 2021 TerraPower, LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

"""
Globally accessible exception definitions for better granularity on exception behavior and
exception handling behavior.
"""
from armi import runLog
from inspect import stack, getframeinfo


[docs]def info(func): """Decorator to write to current log, using the info method.""" def decorated(*args, **kwargs): r"""Decorated method.""" runLog.info(func(*args, **kwargs)) return decorated
[docs]def important(func): """Decorator to write to current log, using the inportant method.""" def decorated(*args, **kwargs): """Decorated method.""" runLog.important(func(*args, **kwargs)) return decorated
[docs]def warn(func): """Decorates a method to produce a repeatable warning message.""" def decorated(*args, **kwargs): """Decorated method.""" runLog.warning(func(*args, **kwargs)) return decorated
def _message_when_root(func): """Do not use this decorator.""" def decorated(*args, **kwargs): from armi import MPI_RANK if MPI_RANK == 0: func(*args, **kwargs) return decorated
[docs]def warn_when_root(func): """Decorates a method to produce a warning message only on the root node.""" return _message_when_root(warn(func))
# ---------------------------------------------------
[docs]class InputError(Exception): """An error found in an ARMI input file.""" def __init__(self, msg): self.msg = msg self.caller = getframeinfo(stack()[1][0]) def __str__(self): # Check if the call site is sensible enough to warrant printing. # In the past, we assumed cython would wrap the fake stack filename in <> callSiteIsFake = self.caller.filename.startswith( "<" ) and self.caller.filename.endswith(">") if callSiteIsFake: return self.msg else: return ( self.caller.filename + ":" + str(self.caller.lineno) + " - " + self.msg )
# ---------------------------------------------------
[docs]class SettingException(Exception): """Standardize behavior of setting-family errors.""" def __init__(self, msg): Exception.__init__(self, msg)
[docs]class InvalidSettingsStopProcess(SettingException): """ Exception raised when setting file contains invalid settings and user aborts or process is uninteractive. """ def __init__(self, reader): msg = "Input settings file {}".format(reader.inputPath) if reader.liveVersion != reader.inputVersion: msg += ( '\n\twas made with version "{0}" which differs from the current version "{1}." ' 'Either create the input file with the "{1}", or switch to a development version ' "of ARMI.".format(reader.inputVersion, reader.liveVersion) ) if reader.invalidSettings: msg += ( "\n\tcontains the following {} invalid settings:\n\t\t" "{}" "".format( len(reader.invalidSettings), "\n\t\t".join(reader.invalidSettings) ) ) SettingException.__init__(self, msg)
[docs]class NonexistentSetting(SettingException): """Exception raised when a non existent setting is asked for.""" def __init__(self, setting): SettingException.__init__( self, "Attempted to locate non-existent setting {}.".format(setting) )
[docs]class InvalidSettingsFileError(SettingException): """Not a valid settings file.""" def __init__(self, path, customMsgEnd=""): msg = "Attempted to load an invalid settings file from: {}. ".format(path) msg += customMsgEnd SettingException.__init__(self, msg)
[docs]class NonexistentSettingsFileError(SettingException): """Settings file does not exist.""" def __init__(self, path): SettingException.__init__( self, "Attempted to load settings file, cannot locate file: {}".format(path) )