Module: check_mk
Branch: master
Commit: f1a612dda86795702567df63b6259da9c9c18205
URL:
http://git.mathias-kettner.de/git/?p=check_mk.git;a=commit;h=f1a612dda86795…
Author: Sven Panne <sp(a)mathias-kettner.de>
Date: Thu Dec 8 10:26:27 2016 +0100
Make our custom exceptions copyable and picklable
By not calling __init__ for the superclass in our own exception's __init__,
we effectively break a required protocol: BaseException needs to know all
arguments to make copy.copy() and pickling work. Furthermore, we get
sensible __str__ and __unicode__ methods, too. Note that we should *not*
modify the arguments when passing them up the __init__ chain, because that
way we break the copy/pickling protocol again.
Starting with Python 3.3, BaseException is more forgiving for such "naive
subclasses" (wording taken from Python's HISTORY file, in effect they mean
"broken" ;-), see the epic 5-year discussion in the Python bug traker at
https://bugs.python.org/issue1692335.
TODO:
* Quite a few custom exceptions needlessly remember a single attribute.
This is subsumed by the superclass's behavior, so a simple "pass"
should be enough. To do this, the attribute access sites have to be
adapted slightly.
* The MKException.__str__ method (including its comment) is bogus, it is
just fighting the str vs. unicode symptom at the wrong place: __str__
should return a str, and __unicode__ should return, well, unicode...
---
cmk_base/localize.py | 1 +
cmk_base/packaging.py | 1 +
lib/exceptions.py | 9 +++++++++
livestatus/api/python/livestatus.py | 20 +++++++-------------
modules/automation.py | 1 +
modules/check_mk_base.py | 4 ++++
scripts/autodetect.py | 5 +++--
web/htdocs/guitester.py | 4 +++-
web/htdocs/html_mod_python.py | 1 +
web/htdocs/htmllib.py | 2 +-
web/htdocs/lib.py | 7 ++++++-
web/htdocs/wato.py | 2 +-
web/htdocs/watolib.py | 2 +-
13 files changed, 39 insertions(+), 20 deletions(-)
diff --git a/cmk_base/localize.py b/cmk_base/localize.py
index 9e1517e..1ee0547 100644
--- a/cmk_base/localize.py
+++ b/cmk_base/localize.py
@@ -37,6 +37,7 @@ logger = cmk.log.get_logger(__name__)
class LocalizeException(Exception):
def __init__(self, reason):
self.reason = reason
+ super(LocalizeException, self).__init__(reason)
def __str__(self):
return self.reason
diff --git a/cmk_base/packaging.py b/cmk_base/packaging.py
index abe089c..b0812f7 100644
--- a/cmk_base/packaging.py
+++ b/cmk_base/packaging.py
@@ -48,6 +48,7 @@ pac_ext = ".mkp"
class PackageException(Exception):
def __init__(self, reason):
self.reason = reason
+ super(PackageException, self).__init__(reason)
def __str__(self):
return self.reason
diff --git a/lib/exceptions.py b/lib/exceptions.py
index 3642b83..1ac4350 100644
--- a/lib/exceptions.py
+++ b/lib/exceptions.py
@@ -37,6 +37,13 @@ except NameError:
# never used directly in the code. Just some wrapper to make all of our
# exceptions handleable with one call
class MKException(Exception):
+ # TODO: The comment and the method below are nonsense: If we want unicode,
+ # it is __unicode__'s task. This just seems to be a workaround for incorrect
+ # call sites confusing both kinds of strings. Sometimes returning a unicode
+ # string below just asks for trouble when e.g. this is spliced into a byte
+ # string, and it *is* a byte string when __str__ is called: Splicing into a
+ # unicode string would call __unicode__.
+ #
# Do not use the Exception() __str__, because it uses str()
# to convert the message. We want to keep unicode strings untouched
# And don't use self.message, because older python versions don't
@@ -49,6 +56,7 @@ class MKException(Exception):
class MKGeneralException(MKException):
def __init__(self, reason):
self.reason = reason
+ super(MKGeneralException, self).__init__(reason)
def __str__(self):
return self.reason
@@ -77,6 +85,7 @@ class MKTerminate(Exception):
class MKBailOut(Exception):
def __init__(self, reason):
self.reason = reason
+ super(MKBailOut, self).__init__(reason)
def __str__(self):
return self.reason
diff --git a/livestatus/api/python/livestatus.py b/livestatus/api/python/livestatus.py
index 2b695bd..7cefeff 100644
--- a/livestatus/api/python/livestatus.py
+++ b/livestatus/api/python/livestatus.py
@@ -59,30 +59,24 @@ remove_cache_regex = re.compile("\nCache:[^\n]*")
class MKLivestatusException(Exception):
def __init__(self, value):
self.parameter = value
+ super(MKLivestatusException, self).__init__(value)
def __str__(self):
return str(self.parameter)
class MKLivestatusSocketError(MKLivestatusException):
- def __init__(self, reason):
- MKLivestatusException.__init__(self, reason)
+ pass
class MKLivestatusSocketClosed(MKLivestatusSocketError):
- def __init__(self, reason):
- MKLivestatusSocketError.__init__(self, reason)
+ pass
class MKLivestatusConfigError(MKLivestatusException):
- def __init__(self, reason):
- MKLivestatusException.__init__(self, reason)
+ pass
class MKLivestatusQueryError(MKLivestatusException):
- def __init__(self, code, reason):
- MKLivestatusException.__init__(self, "%s: %s" % (code, reason))
- self.code = code
+ pass
class MKLivestatusNotFoundError(MKLivestatusException):
- def __init__(self, query):
- MKLivestatusException.__init__(self, query)
- self.query = query
+ pass
# We need some unique value here
NO_DEFAULT = lambda: None
@@ -320,7 +314,7 @@ class BaseConnection:
except:
raise MKLivestatusSocketError("Malformed output")
else:
- raise MKLivestatusQueryError(code, data.strip())
+ raise MKLivestatusQueryError("%s: %s" % (code, data.strip()))
# In case of an IO error or the other side having
# closed the socket do a reconnect and try again, but
diff --git a/modules/automation.py b/modules/automation.py
index 1306d31..f370722 100644
--- a/modules/automation.py
+++ b/modules/automation.py
@@ -35,6 +35,7 @@ import cmk_base.rulesets as rulesets
class MKAutomationError(Exception):
def __init__(self, reason):
self.reason = reason
+ super(MKAutomationError, self).__init__(reason)
def __str__(self):
return self.reason
diff --git a/modules/check_mk_base.py b/modules/check_mk_base.py
index 83ef343..1b23151 100644
--- a/modules/check_mk_base.py
+++ b/modules/check_mk_base.py
@@ -144,12 +144,14 @@ ZERO = 0.0
class MKCounterWrapped(Exception):
def __init__(self, reason):
self.reason = reason
+ super(MKCounterWrapped, self).__init__(reason)
def __str__(self):
return self.reason
class MKAgentError(Exception):
def __init__(self, reason):
self.reason = reason
+ super(MKAgentError, self).__init__(reason)
def __str__(self):
return self.reason
@@ -158,6 +160,7 @@ class MKParseFunctionError(Exception):
self.exception_type = exception_type
self.exception = exception
self.backtrace = backtrace
+ super(MKParseFunctionError, self).__init__(self, exception_type, exception,
backtrace)
def exc_info(self):
return self.exception_type, self.exception, self.backtrace
@@ -168,6 +171,7 @@ class MKParseFunctionError(Exception):
class MKSNMPError(Exception):
def __init__(self, reason):
self.reason = reason
+ super(MKSNMPError, self).__init__(reason)
def __str__(self):
return self.reason
diff --git a/scripts/autodetect.py b/scripts/autodetect.py
index 9bb4bad..5c37e70 100755
--- a/scripts/autodetect.py
+++ b/scripts/autodetect.py
@@ -65,8 +65,9 @@ target_values = {
# /usr/sbin/nagios3 -d /etc/nagios3/nagios.cfg
class Sorry(Exception):
- def __init__(self, text):
- self.reason = text
+ def __init__(self, reason):
+ self.reason = reason
+ super(Sorry, self).__init__(reason)
def find_pid_and_configfile():
procs = os.popen("ps ax -o pid,ppid,user,command").readlines()
diff --git a/web/htdocs/guitester.py b/web/htdocs/guitester.py
index 382aa2a..46674df 100644
--- a/web/htdocs/guitester.py
+++ b/web/htdocs/guitester.py
@@ -37,7 +37,9 @@ import cmk.store as store
class MKGuitestFailed(MKException):
def __init__(self, errors):
self.errors = errors
- MKException.__init__(self, _("GUI Test failed"))
+ super(MKGuitestFailed, self).__init__(errors)
+ def __str__(self):
+ return _("GUI Test failed")
class GUITester:
diff --git a/web/htdocs/html_mod_python.py b/web/htdocs/html_mod_python.py
index 41c885a..308cd91 100644
--- a/web/htdocs/html_mod_python.py
+++ b/web/htdocs/html_mod_python.py
@@ -35,6 +35,7 @@ import cmk.paths
class FinalizeRequest(Exception):
def __init__(self, code = None):
self.status = code or apache.OK
+ super(FinalizeRequest, self).__init__(code)
class html_mod_python(htmllib.html):
diff --git a/web/htdocs/htmllib.py b/web/htdocs/htmllib.py
index 4e33594..97467d1 100644
--- a/web/htdocs/htmllib.py
+++ b/web/htdocs/htmllib.py
@@ -79,7 +79,7 @@ class InvalidUserInput(Exception):
def __init__(self, varname, text):
self.varname = varname
self.text = text
-
+ super(InvalidUserInput, self).__init__(varname, text)
class RequestTimeout(MKException):
pass
diff --git a/web/htdocs/lib.py b/web/htdocs/lib.py
index da18e42..81a88b0 100644
--- a/web/htdocs/lib.py
+++ b/web/htdocs/lib.py
@@ -44,6 +44,7 @@ LOG_DEBUG = 7 # debug-level messages
class MKAuthException(MKException):
def __init__(self, reason):
self.reason = reason
+ super(MKAuthException, self).__init__(reason)
def __str__(self):
return self.reason
@@ -74,7 +75,11 @@ class MKConfigError(MKException):
class MKUserError(MKException):
def __init__(self, varname, message):
self.varname = varname
- super(MKUserError, self).__init__(message)
+ self.message = message
+ super(MKUserError, self).__init__(varname, message)
+
+ def __str__(self):
+ return self.message
def title(self):
return _("Invalid User Input")
diff --git a/web/htdocs/wato.py b/web/htdocs/wato.py
index 2823763..b6dca3c 100644
--- a/web/htdocs/wato.py
+++ b/web/htdocs/wato.py
@@ -8269,7 +8269,7 @@ class ExceptionName(TextAscii):
kwargs["regex"] = "^[-a-z0-9A-Z /]*$"
kwargs["regex_error"] = _("This is not a valid Nagios timeperiod
day specification.")
kwargs["allow_empty"] = False
- TextAscii.__init__(self, **kwargs)
+ super(ExceptionName, self).__init__(**kwargs)
def validate_value(self, value, varprefix):
if value in [ "monday", "tuesday", "wednesday",
"thursday",
diff --git a/web/htdocs/watolib.py b/web/htdocs/watolib.py
index a616305..ed43001 100644
--- a/web/htdocs/watolib.py
+++ b/web/htdocs/watolib.py
@@ -5429,7 +5429,7 @@ def collect_hosts(folder):
class MKAutomationException(Exception):
def __init__(self, msg):
- Exception.__init__(self, msg)
+ super(MKAutomationException, self).__init__(msg)
def check_mk_automation(siteid, command, args=None, indata="", stdin_data=None,
timeout=None, sync=True):