Re-sync with internal repository
[hiphop-php.git] / third-party / folly / src / folly / python / error.cpp
bloba7b919aeb5484723b17c407c99f15cda844670bb
1 /*
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>
19 #include <stdexcept>
20 #include <string>
22 #include <Python.h>
24 #include <folly/Conv.h>
25 #include <folly/ScopeGuard.h>
27 namespace folly {
28 namespace python {
29 namespace {
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;
34 SCOPE_EXIT {
35 Py_XDECREF(pyStr);
36 Py_XDECREF(pyBytes);
37 // Swallow any errors that arise in this function
38 PyErr_Clear();
41 pyStr = PyObject_Repr(obj);
42 if (pyStr == nullptr) {
43 return std::string(kConversionFail);
46 char* cStr = nullptr;
47 #if PY_VERSION_HEX < 0x0300000
48 cStr = PyString_AsString(pyStr);
49 #else
50 pyBytes = PyUnicode_AsEncodedString(pyStr, "utf-8", "strict");
51 if (pyBytes == nullptr) {
52 return std::string(kConversionFail);
55 cStr = PyBytes_AsString(pyBytes);
56 #endif
58 if (cStr == nullptr) {
59 return std::string(kConversionFail);
62 return std::string(cStr);
65 } // namespace
67 void handlePythonError(StringPiece errPrefix) {
68 PyObject *ptype, *pvalue, *ptraceback;
69 SCOPE_EXIT {
70 Py_XDECREF(ptype);
71 Py_XDECREF(pvalue);
72 Py_XDECREF(ptraceback);
74 /**
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)));
93 } // namespace python
94 } // namespace folly