All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
pyError.h
1//
2// Copyright 2016 Pixar
3//
4// Licensed under the terms set forth in the LICENSE.txt file available at
5// https://openusd.org/license.
6//
7#ifndef PXR_BASE_TF_PY_ERROR_H
8#define PXR_BASE_TF_PY_ERROR_H
9
12
13#include "pxr/pxr.h"
14
15#include "pxr/base/tf/api.h"
17
18#include "pxr/external/boost/python/default_call_policies.hpp"
19
20PXR_NAMESPACE_OPEN_SCOPE
21
25TF_API
26bool TfPyConvertTfErrorsToPythonException(TfErrorMark const &m);
27
31TF_API
32void TfPyConvertPythonExceptionToTfErrors();
33
45template <typename Base = pxr_boost::python::default_call_policies>
46struct TfPyRaiseOnError : Base
47{
48 public:
49
50 // This call policy provides a customized argument_package. We need to do
51 // this to store the TfErrorMark that we use to collect TfErrors that
52 // occurred during the call and convert them to a python exception at the
53 // end. It doesn't work to do this in the precall() and postcall()
54 // because if the call itself throws a c++ exception, the postcall() isn't
55 // executed and we can't destroy the TfErrorMark, leaving it dangling.
56 // Using the argument_package solves this since it is a local variable it
57 // will be destroyed whether or not the call throws. This is not really a
58 // publicly documented boost.python feature, however. :-/
59 template <class BaseArgs>
60 struct ErrorMarkAndArgs {
61 /* implicit */ErrorMarkAndArgs(BaseArgs base_) : base(base_) {}
62 operator const BaseArgs &() const { return base; }
63 operator BaseArgs &() { return base; }
64 BaseArgs base;
65 TfErrorMark errorMark;
66 };
67 typedef ErrorMarkAndArgs<typename Base::argument_package> argument_package;
68
71
72 // Only accept our argument_package type, since we must ensure that we're
73 // using it so we track a TfErrorMark.
74 bool precall(argument_package const &a) { return Base::precall(a); }
75
76 // Only accept our argument_package type, since we must ensure that we're
77 // using it so we track a TfErrorMark.
78 PyObject *postcall(argument_package const &a, PyObject *result) {
79 result = Base::postcall(a, result);
80 if (result && TfPyConvertTfErrorsToPythonException(a.errorMark)) {
81 Py_DECREF(result);
82 result = NULL;
83 }
84 return result;
85 }
86};
87
88PXR_NAMESPACE_CLOSE_SCOPE
89
90#endif // PXR_BASE_TF_PY_ERROR_H
Class used to record the end of the error-list.
Definition: errorMark.h:48
A boost.python call policy class which, when applied to a wrapped function, will create an error mark...
Definition: pyError.h:47
TfPyRaiseOnError()
Default constructor.
Definition: pyError.h:70