diff --git a/CMakeLists.txt b/CMakeLists.txt index f0683225cd..6b374643e2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -371,6 +371,7 @@ set(CORE_SOURCE src/ChunkInfo.cpp src/Dataset.cpp src/Datatype.cpp + src/Error.cpp src/Format.cpp src/Iteration.cpp src/IterationEncoding.cpp @@ -410,10 +411,12 @@ set(IO_SOURCE src/IO/ADIOS/ADIOS2PreloadAttributes.cpp src/IO/InvalidatableFile.cpp) set(IO_ADIOS1_SEQUENTIAL_SOURCE + src/Error.cpp src/auxiliary/Filesystem.cpp src/ChunkInfo.cpp src/IO/ADIOS/ADIOS1IOHandler.cpp) set(IO_ADIOS1_SOURCE + src/Error.cpp src/auxiliary/Filesystem.cpp src/ChunkInfo.cpp src/IO/ADIOS/ParallelADIOS1IOHandler.cpp) @@ -627,6 +630,7 @@ if(openPMD_HAVE_PYTHON) src/binding/python/Container.cpp src/binding/python/Dataset.cpp src/binding/python/Datatype.cpp + src/binding/python/Error.cpp src/binding/python/Helper.cpp src/binding/python/Iteration.cpp src/binding/python/IterationEncoding.cpp diff --git a/include/openPMD/Error.hpp b/include/openPMD/Error.hpp new file mode 100644 index 0000000000..84db417275 --- /dev/null +++ b/include/openPMD/Error.hpp @@ -0,0 +1,54 @@ +#pragma once + +#include +#include +#include + +namespace openPMD +{ +/** + * @brief Base class for all openPMD-specific error types. + * + * Should not be instantiated directly, but only by implementing child classes + * in the openPMD::error namespace. + * + */ +class Error : public std::exception +{ +private: + std::string m_what; + +protected: + Error( std::string what ) : m_what( what ) + { + } + +public: + virtual const char * what() const noexcept; + + Error( Error const & ) = default; + Error( Error && ) = default; + + Error & operator=( Error const & ) = default; + Error & operator=( Error && ) = default; + + virtual ~Error() noexcept = default; +}; + +namespace error +{ + /** + * @brief An operation was requested that is not supported in a specific + * backend. + * + * Example: Append mode is not available in ADIOS1. + */ + class OperationUnsupportedInBackend : public Error + { + public: + std::string backend; + OperationUnsupportedInBackend( + std::string backend_in, std::string what ); + }; +} +} diff --git a/include/openPMD/openPMD.hpp b/include/openPMD/openPMD.hpp index b5625e3191..c4078ba2c0 100644 --- a/include/openPMD/openPMD.hpp +++ b/include/openPMD/openPMD.hpp @@ -27,6 +27,7 @@ namespace openPMD {} // IWYU pragma: begin_exports #include "openPMD/Dataset.hpp" #include "openPMD/Datatype.hpp" +#include "openPMD/Error.hpp" #include "openPMD/IterationEncoding.hpp" #include "openPMD/Iteration.hpp" #include "openPMD/Mesh.hpp" diff --git a/src/Error.cpp b/src/Error.cpp new file mode 100644 index 0000000000..9998784276 --- /dev/null +++ b/src/Error.cpp @@ -0,0 +1,19 @@ +#include "openPMD/Error.hpp" + +namespace openPMD +{ +const char * Error::what() const noexcept +{ + return m_what.c_str(); +} + +namespace error +{ + OperationUnsupportedInBackend::OperationUnsupportedInBackend( + std::string backend_in, std::string what ) + : Error( "Operation unsupported in " + backend_in + ": " + what ) + , backend{ std::move( backend_in ) } + { + } +} +} diff --git a/src/binding/python/Error.cpp b/src/binding/python/Error.cpp new file mode 100644 index 0000000000..f0c218e1a0 --- /dev/null +++ b/src/binding/python/Error.cpp @@ -0,0 +1,19 @@ +#include "openPMD/Error.hpp" + +#include + +namespace py = pybind11; +using namespace openPMD; + +void init_Error( py::module & m ) +{ + auto & baseError = py::register_exception< Error >( m, "Error" ); + py::register_exception< error::OperationUnsupportedInBackend >( + m, "ErrorOperationUnsupportedInBackend", baseError ); + +#ifndef NDEBUG + m.def( "test_throw", []( std::string description ) { + throw error::OperationUnsupportedInBackend( "json", description ); + } ); +#endif +} diff --git a/src/binding/python/openPMD.cpp b/src/binding/python/openPMD.cpp index 2b9d6b2c1b..583117a182 100644 --- a/src/binding/python/openPMD.cpp +++ b/src/binding/python/openPMD.cpp @@ -40,6 +40,7 @@ void init_Chunk(py::module &m); void init_Container(py::module &); void init_Dataset(py::module &); void init_Datatype(py::module &); +void init_Error(py::module &); void init_Helper(py::module &); void init_Iteration(py::module &); void init_IterationEncoding(py::module &); @@ -90,6 +91,7 @@ PYBIND11_MODULE(openpmd_api_cxx, m) { init_Attributable(m); init_Chunk(m); init_Container(m); + init_Error(m); init_BaseRecord(m); init_Dataset(m); init_Datatype(m); diff --git a/test/python/unittest/API/APITest.py b/test/python/unittest/API/APITest.py index 879d50aef2..28eafec970 100644 --- a/test/python/unittest/API/APITest.py +++ b/test/python/unittest/API/APITest.py @@ -1997,6 +1997,13 @@ def testJsonConfigADIOS2(self): self.assertEqual(chunk_x[i], i) self.assertEqual(chunk_y[i], i) + def testError(self): + if 'test_throw' in io.__dict__: + with self.assertRaises(io.ErrorOperationUnsupportedInBackend): + io.test_throw("test description") + with self.assertRaises(io.Error): + io.test_throw("test description") + def testCustomGeometries(self): DS = io.Dataset DT = io.Datatype