1 /* Copyright 2018 The TensorFlow Authors. All Rights Reserved. 2 3 Licensed under the Apache License, Version 2.0 (the "License"); 4 you may not use this file except in compliance with the License. 5 You may obtain a copy of the License at 6 7 http://www.apache.org/licenses/LICENSE-2.0 8 9 Unless required by applicable law or agreed to in writing, software 10 distributed under the License is distributed on an "AS IS" BASIS, 11 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 See the License for the specific language governing permissions and 13 limitations under the License. 14 ==============================================================================*/ 15 #ifndef TENSORFLOW_PYTHON_LIB_CORE_PY_EXCEPTION_REGISTRY_H_ 16 #define TENSORFLOW_PYTHON_LIB_CORE_PY_EXCEPTION_REGISTRY_H_ 17 18 #include <map> 19 20 #include "tensorflow/c/c_api.h" 21 #include "tensorflow/core/platform/logging.h" 22 23 #ifndef PyObject_HEAD 24 struct _object; 25 typedef _object PyObject; 26 #endif 27 28 namespace tensorflow { 29 30 // Global registry mapping C API error codes to the corresponding custom Python 31 // exception type. This is used to expose the exception types to C extension 32 // code (i.e. so we can raise custom exceptions via SWIG). 33 // 34 // Init() must be called exactly once at the beginning of the process before 35 // Lookup() can be used. 36 // 37 // Example usage: 38 // TF_Status* status = TF_NewStatus(); 39 // TF_Foo(..., status); 40 // 41 // if (TF_GetCode(status) != TF_OK) { 42 // PyObject* exc_type = PyExceptionRegistry::Lookup(TF_GetCode(status)); 43 // // Arguments to OpError base class. Set `node_def` and `op` to None. 44 // PyObject* args = 45 // Py_BuildValue("sss", nullptr, nullptr, TF_Message(status)); 46 // PyErr_SetObject(exc_type, args); 47 // Py_DECREF(args); 48 // TF_DeleteStatus(status); 49 // return NULL; 50 // } 51 class PyExceptionRegistry { 52 public: 53 // Initializes the process-wide registry. Should be called exactly once near 54 // the beginning of the process. The arguments are the various Python 55 // exception types (e.g. `cancelled_exc` corresponds to 56 // errors.CancelledError). 57 static void Init(PyObject* code_to_exc_type_map); 58 59 // Returns the Python exception type corresponding to `code`. Init() must be 60 // called before using this function. `code` should not be TF_OK. 61 static PyObject* Lookup(TF_Code code); 62 63 private: 64 static PyExceptionRegistry* singleton_; 65 PyExceptionRegistry() = default; 66 67 // Maps error codes to the corresponding Python exception type. 68 std::map<TF_Code, PyObject*> exc_types_; 69 }; 70 71 } // namespace tensorflow 72 73 #endif // TENSORFLOW_PYTHON_LIB_CORE_PY_EXCEPTION_REGISTRY_H_ 74