RIFT OSM R1 Initial Submission
[osm/SO.git] / rwcal / rift / cal / rwcal_status.py
diff --git a/rwcal/rift/cal/rwcal_status.py b/rwcal/rift/cal/rwcal_status.py
new file mode 100644 (file)
index 0000000..6867140
--- /dev/null
@@ -0,0 +1,86 @@
+#!/usr/bin/env python
+# 
+#   Copyright 2016 RIFT.IO Inc
+#
+#   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.
+#
+#
+# @file rwcal_status.py
+# @brief This module defines Python utilities for dealing with rwcalstatus codes.
+
+import traceback
+import functools
+import gi
+gi.require_version('RwTypes', '1.0')
+
+from gi.repository import RwTypes, RwCal
+
+def rwcalstatus_from_exc_map(exc_map):
+    """ Creates an rwcalstatus decorator from a dictionary mapping exception
+    types to rwstatus codes, and return a error object containing Exception details
+    """
+
+    # A decorator that maps a Python exception to a particular return code.
+    # Also returns an object containing the error msg, traceback and rwstatus
+    # Automatically returns RW_SUCCESS when no Python exception was thrown.
+    # Prevents us from having to use try: except: handlers around every function call.
+
+    def rwstatus(arg=None, ret_on_failure=None):
+        def decorator(func):
+            @functools.wraps(func)
+            def wrapper(*args, **kwds):
+                rwcal_status = RwCal.RwcalStatus()
+                try:
+                    ret = func(*args, **kwds)
+
+                except Exception as e:
+                    rwcal_status.traceback = traceback.format_exc()
+                    rwcal_status.error_msg = str(e)
+
+                    ret_code = [status for exc, status in exc_map.items() if isinstance(e, exc)]
+                    ret_list = [None] if ret_on_failure is None else list(ret_on_failure)
+                    if len(ret_code):
+                        rwcal_status.status = ret_code[0]
+                    else:
+                        # If it was not explicitly mapped, print the full traceback as this
+                        # is not an anticipated error.
+                        traceback.print_exc()
+                        rwcal_status.status = RwTypes.RwStatus.FAILURE
+
+                    ret_list.insert(0, rwcal_status)
+                    return tuple(ret_list)
+
+
+                rwcal_status.status = RwTypes.RwStatus.SUCCESS
+                rwcal_status.traceback = ""
+                rwcal_status.error_msg = ""
+                ret_list = [rwcal_status]
+                if ret is not None:
+                    if type(ret) == tuple:
+                        ret_list.extend(ret)
+                    else:
+                        ret_list.append(ret)
+
+                return tuple(ret_list)
+
+            return wrapper
+
+        if isinstance(arg, dict):
+            exc_map.update(arg)
+            return decorator
+        elif ret_on_failure is not None:
+            return decorator
+        else:
+            return decorator(arg)
+
+    return rwstatus