diff options
author | say <say@yandex-team.com> | 2023-02-14 17:24:43 +0300 |
---|---|---|
committer | say <say@yandex-team.com> | 2023-02-14 17:24:43 +0300 |
commit | e0094c4ad6964e11564777bc0d859c68d8aa9de2 (patch) | |
tree | 5d2ad1a4df88da1f74385888891a2a5f9fbbc3ef /library/cpp/pybind/exceptions.h | |
parent | 65a08c9fdece8dba50da8beb4d7c81447211dd45 (diff) | |
download | ydb-e0094c4ad6964e11564777bc0d859c68d8aa9de2.tar.gz |
Migrate black linter on custom_lint pipeline
Diffstat (limited to 'library/cpp/pybind/exceptions.h')
-rw-r--r-- | library/cpp/pybind/exceptions.h | 143 |
1 files changed, 143 insertions, 0 deletions
diff --git a/library/cpp/pybind/exceptions.h b/library/cpp/pybind/exceptions.h new file mode 100644 index 0000000000..48e20995e4 --- /dev/null +++ b/library/cpp/pybind/exceptions.h @@ -0,0 +1,143 @@ +#pragma once + +#define PY_SSIZE_T_CLEAN +#include <Python.h> +#include <util/generic/yexception.h> +#include <util/generic/map.h> +#include <util/generic/vector.h> +#include "ptr.h" + +namespace NPyBind { + // Usage: + // ythrow TPyErr(PyExc_TypeError) << "some python type error somewhere in your C++ code"; + // + class TPyErr: public virtual yexception { + public: + TPyErr(PyObject* theException = PyExc_RuntimeError) + : Exception(theException) + { + } + + TPyObjectPtr GetException() const { + return Exception; + } + + private: + NPyBind::TPyObjectPtr Exception; + }; + + //Private api for creating PyBind python module + //Needs only for overriding pybind python module in library which imports other pybind library + namespace NPrivate { + TPyObjectPtr CreatePyBindModule(); + }//NPrivate + class TExceptionsHolder { + friend TPyObjectPtr NPrivate::CreatePyBindModule(); + private: + TExceptionsHolder(const TExceptionsHolder&); + TExceptionsHolder& operator=(const TExceptionsHolder&); + TExceptionsHolder(); + + void Clear(); + TPyObjectPtr GetException(const TString&); + TPyObjectPtr GetExceptions(const TVector<TString>&); + private: + class TExceptionsChecker { + public: + virtual ~TExceptionsChecker() { + } + virtual bool Check(const std::exception& ex) const = 0; + virtual TString GetName() const = 0; + virtual TPyObjectPtr GetException() const = 0; + }; + + template <typename TExcType> + class TConcreteExceptionsChecker: public TExceptionsChecker { + private: + TString Name; + TPyObjectPtr Exception; + + public: + TConcreteExceptionsChecker(const TString& name, TPyObjectPtr exception) + : Name(name) + , Exception(exception) + { + } + + bool Check(const std::exception& ex) const override { + const std::exception* e = &ex; + return dynamic_cast<const TExcType*>(e); + } + + TString GetName() const override { + return Name; + } + + TPyObjectPtr GetException() const override { + return Exception; + } + }; + + class TPyErrExceptionsChecker: public TExceptionsChecker { + private: + mutable TPyObjectPtr Exception; + + public: + TPyErrExceptionsChecker() { + } + + bool Check(const std::exception& ex) const override { + const TPyErr* err = dynamic_cast<const TPyErr*>(&ex); + if (err) { + Exception = err->GetException(); + } + return err != nullptr; + } + + TString GetName() const override { + return TString(); + } + + TPyObjectPtr GetException() const override { + return Exception; + } + }; + + typedef TSimpleSharedPtr<TExceptionsChecker> TCheckerPtr; + typedef TVector<TCheckerPtr> TCheckersVector; + typedef TMap<TString, TPyObjectPtr> TExceptionsMap; + + TPyObjectPtr Module; + TCheckersVector Checkers; + TExceptionsMap Exceptions; + + static PyObject* DoInitPyBindModule(); + static void DoInitPyBindModule2(); + + public: + static TExceptionsHolder& Instance() { + static TExceptionsHolder Holder; + return Holder; + } + + template <typename TExcType> + void AddException(const TString& name, const TString& base = "") { + TPyObjectPtr baseException(GetException(base)); + TString fullName = TString("pybind.") + name; + TPyObjectPtr exception(PyErr_NewException(const_cast<char*>(fullName.c_str()), baseException.Get(), nullptr), true); + Checkers.push_back(new TConcreteExceptionsChecker<TExcType>(name, exception)); + Exceptions[name] = exception; + } + + template <typename TExcType> + void AddException(const TString& name, const TVector<TString>& bases) { + TPyObjectPtr baseExceptions(GetExceptions(bases)); + TString fullName = TString("pybind.") + name; + TPyObjectPtr exception(PyErr_NewException(const_cast<char*>(fullName.c_str()), baseExceptions.Get(), nullptr), true); + Checkers.push_back(new TConcreteExceptionsChecker<TExcType>(name, exception)); + Exceptions[name] = exception; + } + + NPyBind::TPyObjectPtr ToPyException(const std::exception&); + }; +} |