2 * Copyright (c) Meta Platforms, Inc. and affiliates.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
17 #include <folly/python/error.h>
24 #include <folly/Conv.h>
25 #include <folly/ScopeGuard.h>
30 // Best effort c-api implementation of repr(obj)
31 std::string
pyObjectToString(PyObject
* obj
) {
32 constexpr StringPiece kConversionFail
= "Error conversion failed";
33 PyObject
*pyStr
, *pyBytes
;
37 // Swallow any errors that arise in this function
41 pyStr
= PyObject_Repr(obj
);
42 if (pyStr
== nullptr) {
43 return std::string(kConversionFail
);
47 #if PY_VERSION_HEX < 0x0300000
48 cStr
= PyString_AsString(pyStr
);
50 pyBytes
= PyUnicode_AsEncodedString(pyStr
, "utf-8", "strict");
51 if (pyBytes
== nullptr) {
52 return std::string(kConversionFail
);
55 cStr
= PyBytes_AsString(pyBytes
);
58 if (cStr
== nullptr) {
59 return std::string(kConversionFail
);
62 return std::string(cStr
);
67 void handlePythonError(StringPiece errPrefix
) {
68 PyObject
*ptype
, *pvalue
, *ptraceback
;
72 Py_XDECREF(ptraceback
);
75 * PyErr_Fetch will clear the error indicator (which *should* be set here, but
76 * let's not assume it is)
78 PyErr_Fetch(&ptype
, &pvalue
, &ptraceback
);
80 if (ptype
== nullptr) {
81 throw std::runtime_error(
82 to
<std::string
>(errPrefix
, "No error indicator set"));
85 if (pvalue
== nullptr) {
86 throw std::runtime_error(to
<std::string
>(
87 errPrefix
, "Exception of type: ", pyObjectToString(ptype
)));
90 throw std::runtime_error(
91 to
<std::string
>(errPrefix
, pyObjectToString(pvalue
)));