xref: /freebsd-src/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.cpp (revision 81ad626541db97eb356e2c1d4a20eb2a26a766ab)
15ffd83dbSDimitry Andric //===-- PythonDataObjects.cpp ---------------------------------------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric 
9480093f4SDimitry Andric #include "lldb/Host/Config.h"
100b57cec5SDimitry Andric 
11480093f4SDimitry Andric #if LLDB_ENABLE_PYTHON
120b57cec5SDimitry Andric 
130b57cec5SDimitry Andric #include "PythonDataObjects.h"
140b57cec5SDimitry Andric #include "ScriptInterpreterPython.h"
150b57cec5SDimitry Andric 
160b57cec5SDimitry Andric #include "lldb/Host/File.h"
170b57cec5SDimitry Andric #include "lldb/Host/FileSystem.h"
180b57cec5SDimitry Andric #include "lldb/Interpreter/ScriptInterpreter.h"
19*81ad6265SDimitry Andric #include "lldb/Utility/LLDBLog.h"
209dba64beSDimitry Andric #include "lldb/Utility/Log.h"
210b57cec5SDimitry Andric #include "lldb/Utility/Stream.h"
220b57cec5SDimitry Andric 
230b57cec5SDimitry Andric #include "llvm/ADT/StringSwitch.h"
249dba64beSDimitry Andric #include "llvm/Support/Casting.h"
250b57cec5SDimitry Andric #include "llvm/Support/ConvertUTF.h"
260b57cec5SDimitry Andric #include "llvm/Support/Errno.h"
270b57cec5SDimitry Andric 
28fe6060f1SDimitry Andric #include <cstdio>
290b57cec5SDimitry Andric 
300b57cec5SDimitry Andric using namespace lldb_private;
310b57cec5SDimitry Andric using namespace lldb;
329dba64beSDimitry Andric using namespace lldb_private::python;
339dba64beSDimitry Andric using llvm::cantFail;
349dba64beSDimitry Andric using llvm::Error;
359dba64beSDimitry Andric using llvm::Expected;
369dba64beSDimitry Andric using llvm::Twine;
370b57cec5SDimitry Andric 
389dba64beSDimitry Andric template <> Expected<bool> python::As<bool>(Expected<PythonObject> &&obj) {
399dba64beSDimitry Andric   if (!obj)
409dba64beSDimitry Andric     return obj.takeError();
419dba64beSDimitry Andric   return obj.get().IsTrue();
429dba64beSDimitry Andric }
439dba64beSDimitry Andric 
449dba64beSDimitry Andric template <>
459dba64beSDimitry Andric Expected<long long> python::As<long long>(Expected<PythonObject> &&obj) {
469dba64beSDimitry Andric   if (!obj)
479dba64beSDimitry Andric     return obj.takeError();
485ffd83dbSDimitry Andric   return obj->AsLongLong();
495ffd83dbSDimitry Andric }
505ffd83dbSDimitry Andric 
515ffd83dbSDimitry Andric template <>
525ffd83dbSDimitry Andric Expected<unsigned long long>
535ffd83dbSDimitry Andric python::As<unsigned long long>(Expected<PythonObject> &&obj) {
545ffd83dbSDimitry Andric   if (!obj)
555ffd83dbSDimitry Andric     return obj.takeError();
565ffd83dbSDimitry Andric   return obj->AsUnsignedLongLong();
579dba64beSDimitry Andric }
589dba64beSDimitry Andric 
599dba64beSDimitry Andric template <>
609dba64beSDimitry Andric Expected<std::string> python::As<std::string>(Expected<PythonObject> &&obj) {
619dba64beSDimitry Andric   if (!obj)
629dba64beSDimitry Andric     return obj.takeError();
639dba64beSDimitry Andric   PyObject *str_obj = PyObject_Str(obj.get().get());
649dba64beSDimitry Andric   if (!obj)
659dba64beSDimitry Andric     return llvm::make_error<PythonException>();
669dba64beSDimitry Andric   auto str = Take<PythonString>(str_obj);
679dba64beSDimitry Andric   auto utf8 = str.AsUTF8();
689dba64beSDimitry Andric   if (!utf8)
699dba64beSDimitry Andric     return utf8.takeError();
705ffd83dbSDimitry Andric   return std::string(utf8.get());
715ffd83dbSDimitry Andric }
725ffd83dbSDimitry Andric 
7304eeddc0SDimitry Andric static bool python_is_finalizing() {
74*81ad6265SDimitry Andric #if PY_MAJOR_VERSION == 3 && PY_MINOR_VERSION < 7
7504eeddc0SDimitry Andric   return _Py_Finalizing != nullptr;
7604eeddc0SDimitry Andric #else
7704eeddc0SDimitry Andric   return _Py_IsFinalizing();
7804eeddc0SDimitry Andric #endif
7904eeddc0SDimitry Andric }
8004eeddc0SDimitry Andric 
8104eeddc0SDimitry Andric void PythonObject::Reset() {
8204eeddc0SDimitry Andric   if (m_py_obj && Py_IsInitialized()) {
8304eeddc0SDimitry Andric     if (python_is_finalizing()) {
8404eeddc0SDimitry Andric       // Leak m_py_obj rather than crashing the process.
8504eeddc0SDimitry Andric       // https://docs.python.org/3/c-api/init.html#c.PyGILState_Ensure
8604eeddc0SDimitry Andric     } else {
8704eeddc0SDimitry Andric       PyGILState_STATE state = PyGILState_Ensure();
8804eeddc0SDimitry Andric       Py_DECREF(m_py_obj);
8904eeddc0SDimitry Andric       PyGILState_Release(state);
9004eeddc0SDimitry Andric     }
9104eeddc0SDimitry Andric   }
9204eeddc0SDimitry Andric   m_py_obj = nullptr;
9304eeddc0SDimitry Andric }
9404eeddc0SDimitry Andric 
955ffd83dbSDimitry Andric Expected<long long> PythonObject::AsLongLong() const {
965ffd83dbSDimitry Andric   if (!m_py_obj)
975ffd83dbSDimitry Andric     return nullDeref();
985ffd83dbSDimitry Andric   assert(!PyErr_Occurred());
995ffd83dbSDimitry Andric   long long r = PyLong_AsLongLong(m_py_obj);
1005ffd83dbSDimitry Andric   if (PyErr_Occurred())
1015ffd83dbSDimitry Andric     return exception();
1025ffd83dbSDimitry Andric   return r;
1035ffd83dbSDimitry Andric }
1045ffd83dbSDimitry Andric 
1055ffd83dbSDimitry Andric Expected<long long> PythonObject::AsUnsignedLongLong() const {
1065ffd83dbSDimitry Andric   if (!m_py_obj)
1075ffd83dbSDimitry Andric     return nullDeref();
1085ffd83dbSDimitry Andric   assert(!PyErr_Occurred());
1095ffd83dbSDimitry Andric   long long r = PyLong_AsUnsignedLongLong(m_py_obj);
1105ffd83dbSDimitry Andric   if (PyErr_Occurred())
1115ffd83dbSDimitry Andric     return exception();
1125ffd83dbSDimitry Andric   return r;
1135ffd83dbSDimitry Andric }
1145ffd83dbSDimitry Andric 
1155ffd83dbSDimitry Andric // wraps on overflow, instead of raising an error.
1165ffd83dbSDimitry Andric Expected<unsigned long long> PythonObject::AsModuloUnsignedLongLong() const {
1175ffd83dbSDimitry Andric   if (!m_py_obj)
1185ffd83dbSDimitry Andric     return nullDeref();
1195ffd83dbSDimitry Andric   assert(!PyErr_Occurred());
1205ffd83dbSDimitry Andric   unsigned long long r = PyLong_AsUnsignedLongLongMask(m_py_obj);
1215ffd83dbSDimitry Andric   if (PyErr_Occurred())
1225ffd83dbSDimitry Andric     return exception();
1235ffd83dbSDimitry Andric   return r;
1249dba64beSDimitry Andric }
1259dba64beSDimitry Andric 
1269dba64beSDimitry Andric void StructuredPythonObject::Serialize(llvm::json::OStream &s) const {
1279dba64beSDimitry Andric   s.value(llvm::formatv("Python Obj: {0:X}", GetValue()).str());
1280b57cec5SDimitry Andric }
1290b57cec5SDimitry Andric 
1300b57cec5SDimitry Andric // PythonObject
1310b57cec5SDimitry Andric 
1320b57cec5SDimitry Andric void PythonObject::Dump(Stream &strm) const {
1330b57cec5SDimitry Andric   if (m_py_obj) {
1340b57cec5SDimitry Andric     FILE *file = llvm::sys::RetryAfterSignal(nullptr, ::tmpfile);
1350b57cec5SDimitry Andric     if (file) {
1360b57cec5SDimitry Andric       ::PyObject_Print(m_py_obj, file, 0);
1370b57cec5SDimitry Andric       const long length = ftell(file);
1380b57cec5SDimitry Andric       if (length) {
1390b57cec5SDimitry Andric         ::rewind(file);
1400b57cec5SDimitry Andric         std::vector<char> file_contents(length, '\0');
1410b57cec5SDimitry Andric         const size_t length_read =
1420b57cec5SDimitry Andric             ::fread(file_contents.data(), 1, file_contents.size(), file);
1430b57cec5SDimitry Andric         if (length_read > 0)
1440b57cec5SDimitry Andric           strm.Write(file_contents.data(), length_read);
1450b57cec5SDimitry Andric       }
1460b57cec5SDimitry Andric       ::fclose(file);
1470b57cec5SDimitry Andric     }
1480b57cec5SDimitry Andric   } else
1490b57cec5SDimitry Andric     strm.PutCString("NULL");
1500b57cec5SDimitry Andric }
1510b57cec5SDimitry Andric 
1520b57cec5SDimitry Andric PyObjectType PythonObject::GetObjectType() const {
1530b57cec5SDimitry Andric   if (!IsAllocated())
1540b57cec5SDimitry Andric     return PyObjectType::None;
1550b57cec5SDimitry Andric 
1560b57cec5SDimitry Andric   if (PythonModule::Check(m_py_obj))
1570b57cec5SDimitry Andric     return PyObjectType::Module;
1580b57cec5SDimitry Andric   if (PythonList::Check(m_py_obj))
1590b57cec5SDimitry Andric     return PyObjectType::List;
1600b57cec5SDimitry Andric   if (PythonTuple::Check(m_py_obj))
1610b57cec5SDimitry Andric     return PyObjectType::Tuple;
1620b57cec5SDimitry Andric   if (PythonDictionary::Check(m_py_obj))
1630b57cec5SDimitry Andric     return PyObjectType::Dictionary;
1640b57cec5SDimitry Andric   if (PythonString::Check(m_py_obj))
1650b57cec5SDimitry Andric     return PyObjectType::String;
1660b57cec5SDimitry Andric   if (PythonBytes::Check(m_py_obj))
1670b57cec5SDimitry Andric     return PyObjectType::Bytes;
1680b57cec5SDimitry Andric   if (PythonByteArray::Check(m_py_obj))
1690b57cec5SDimitry Andric     return PyObjectType::ByteArray;
1700b57cec5SDimitry Andric   if (PythonBoolean::Check(m_py_obj))
1710b57cec5SDimitry Andric     return PyObjectType::Boolean;
1720b57cec5SDimitry Andric   if (PythonInteger::Check(m_py_obj))
1730b57cec5SDimitry Andric     return PyObjectType::Integer;
1740b57cec5SDimitry Andric   if (PythonFile::Check(m_py_obj))
1750b57cec5SDimitry Andric     return PyObjectType::File;
1760b57cec5SDimitry Andric   if (PythonCallable::Check(m_py_obj))
1770b57cec5SDimitry Andric     return PyObjectType::Callable;
1780b57cec5SDimitry Andric   return PyObjectType::Unknown;
1790b57cec5SDimitry Andric }
1800b57cec5SDimitry Andric 
1810b57cec5SDimitry Andric PythonString PythonObject::Repr() const {
1820b57cec5SDimitry Andric   if (!m_py_obj)
1830b57cec5SDimitry Andric     return PythonString();
1840b57cec5SDimitry Andric   PyObject *repr = PyObject_Repr(m_py_obj);
1850b57cec5SDimitry Andric   if (!repr)
1860b57cec5SDimitry Andric     return PythonString();
1870b57cec5SDimitry Andric   return PythonString(PyRefType::Owned, repr);
1880b57cec5SDimitry Andric }
1890b57cec5SDimitry Andric 
1900b57cec5SDimitry Andric PythonString PythonObject::Str() const {
1910b57cec5SDimitry Andric   if (!m_py_obj)
1920b57cec5SDimitry Andric     return PythonString();
1930b57cec5SDimitry Andric   PyObject *str = PyObject_Str(m_py_obj);
1940b57cec5SDimitry Andric   if (!str)
1950b57cec5SDimitry Andric     return PythonString();
1960b57cec5SDimitry Andric   return PythonString(PyRefType::Owned, str);
1970b57cec5SDimitry Andric }
1980b57cec5SDimitry Andric 
1990b57cec5SDimitry Andric PythonObject
2000b57cec5SDimitry Andric PythonObject::ResolveNameWithDictionary(llvm::StringRef name,
2010b57cec5SDimitry Andric                                         const PythonDictionary &dict) {
2020b57cec5SDimitry Andric   size_t dot_pos = name.find('.');
2030b57cec5SDimitry Andric   llvm::StringRef piece = name.substr(0, dot_pos);
2040b57cec5SDimitry Andric   PythonObject result = dict.GetItemForKey(PythonString(piece));
2050b57cec5SDimitry Andric   if (dot_pos == llvm::StringRef::npos) {
2060b57cec5SDimitry Andric     // There was no dot, we're done.
2070b57cec5SDimitry Andric     return result;
2080b57cec5SDimitry Andric   }
2090b57cec5SDimitry Andric 
2100b57cec5SDimitry Andric   // There was a dot.  The remaining portion of the name should be looked up in
2110b57cec5SDimitry Andric   // the context of the object that was found in the dictionary.
2120b57cec5SDimitry Andric   return result.ResolveName(name.substr(dot_pos + 1));
2130b57cec5SDimitry Andric }
2140b57cec5SDimitry Andric 
2150b57cec5SDimitry Andric PythonObject PythonObject::ResolveName(llvm::StringRef name) const {
2160b57cec5SDimitry Andric   // Resolve the name in the context of the specified object.  If, for example,
2170b57cec5SDimitry Andric   // `this` refers to a PyModule, then this will look for `name` in this
2180b57cec5SDimitry Andric   // module.  If `this` refers to a PyType, then it will resolve `name` as an
2190b57cec5SDimitry Andric   // attribute of that type.  If `this` refers to an instance of an object,
2200b57cec5SDimitry Andric   // then it will resolve `name` as the value of the specified field.
2210b57cec5SDimitry Andric   //
2220b57cec5SDimitry Andric   // This function handles dotted names so that, for example, if `m_py_obj`
2230b57cec5SDimitry Andric   // refers to the `sys` module, and `name` == "path.append", then it will find
2240b57cec5SDimitry Andric   // the function `sys.path.append`.
2250b57cec5SDimitry Andric 
2260b57cec5SDimitry Andric   size_t dot_pos = name.find('.');
2270b57cec5SDimitry Andric   if (dot_pos == llvm::StringRef::npos) {
2280b57cec5SDimitry Andric     // No dots in the name, we should be able to find the value immediately as
2290b57cec5SDimitry Andric     // an attribute of `m_py_obj`.
2300b57cec5SDimitry Andric     return GetAttributeValue(name);
2310b57cec5SDimitry Andric   }
2320b57cec5SDimitry Andric 
2330b57cec5SDimitry Andric   // Look up the first piece of the name, and resolve the rest as a child of
2340b57cec5SDimitry Andric   // that.
2350b57cec5SDimitry Andric   PythonObject parent = ResolveName(name.substr(0, dot_pos));
2360b57cec5SDimitry Andric   if (!parent.IsAllocated())
2370b57cec5SDimitry Andric     return PythonObject();
2380b57cec5SDimitry Andric 
2390b57cec5SDimitry Andric   // Tail recursion.. should be optimized by the compiler
2400b57cec5SDimitry Andric   return parent.ResolveName(name.substr(dot_pos + 1));
2410b57cec5SDimitry Andric }
2420b57cec5SDimitry Andric 
2430b57cec5SDimitry Andric bool PythonObject::HasAttribute(llvm::StringRef attr) const {
2440b57cec5SDimitry Andric   if (!IsValid())
2450b57cec5SDimitry Andric     return false;
2460b57cec5SDimitry Andric   PythonString py_attr(attr);
2470b57cec5SDimitry Andric   return !!PyObject_HasAttr(m_py_obj, py_attr.get());
2480b57cec5SDimitry Andric }
2490b57cec5SDimitry Andric 
2500b57cec5SDimitry Andric PythonObject PythonObject::GetAttributeValue(llvm::StringRef attr) const {
2510b57cec5SDimitry Andric   if (!IsValid())
2520b57cec5SDimitry Andric     return PythonObject();
2530b57cec5SDimitry Andric 
2540b57cec5SDimitry Andric   PythonString py_attr(attr);
2550b57cec5SDimitry Andric   if (!PyObject_HasAttr(m_py_obj, py_attr.get()))
2560b57cec5SDimitry Andric     return PythonObject();
2570b57cec5SDimitry Andric 
2580b57cec5SDimitry Andric   return PythonObject(PyRefType::Owned,
2590b57cec5SDimitry Andric                       PyObject_GetAttr(m_py_obj, py_attr.get()));
2600b57cec5SDimitry Andric }
2610b57cec5SDimitry Andric 
2620b57cec5SDimitry Andric StructuredData::ObjectSP PythonObject::CreateStructuredObject() const {
26304eeddc0SDimitry Andric   assert(PyGILState_Check());
2640b57cec5SDimitry Andric   switch (GetObjectType()) {
2650b57cec5SDimitry Andric   case PyObjectType::Dictionary:
2660b57cec5SDimitry Andric     return PythonDictionary(PyRefType::Borrowed, m_py_obj)
2670b57cec5SDimitry Andric         .CreateStructuredDictionary();
2680b57cec5SDimitry Andric   case PyObjectType::Boolean:
2690b57cec5SDimitry Andric     return PythonBoolean(PyRefType::Borrowed, m_py_obj)
2700b57cec5SDimitry Andric         .CreateStructuredBoolean();
2710b57cec5SDimitry Andric   case PyObjectType::Integer:
2720b57cec5SDimitry Andric     return PythonInteger(PyRefType::Borrowed, m_py_obj)
2730b57cec5SDimitry Andric         .CreateStructuredInteger();
2740b57cec5SDimitry Andric   case PyObjectType::List:
2750b57cec5SDimitry Andric     return PythonList(PyRefType::Borrowed, m_py_obj).CreateStructuredArray();
2760b57cec5SDimitry Andric   case PyObjectType::String:
2770b57cec5SDimitry Andric     return PythonString(PyRefType::Borrowed, m_py_obj).CreateStructuredString();
2780b57cec5SDimitry Andric   case PyObjectType::Bytes:
2790b57cec5SDimitry Andric     return PythonBytes(PyRefType::Borrowed, m_py_obj).CreateStructuredString();
2800b57cec5SDimitry Andric   case PyObjectType::ByteArray:
2810b57cec5SDimitry Andric     return PythonByteArray(PyRefType::Borrowed, m_py_obj)
2820b57cec5SDimitry Andric         .CreateStructuredString();
2830b57cec5SDimitry Andric   case PyObjectType::None:
2840b57cec5SDimitry Andric     return StructuredData::ObjectSP();
2850b57cec5SDimitry Andric   default:
28604eeddc0SDimitry Andric     return StructuredData::ObjectSP(new StructuredPythonObject(
28704eeddc0SDimitry Andric         PythonObject(PyRefType::Borrowed, m_py_obj)));
2880b57cec5SDimitry Andric   }
2890b57cec5SDimitry Andric }
2900b57cec5SDimitry Andric 
2910b57cec5SDimitry Andric // PythonString
2920b57cec5SDimitry Andric 
2939dba64beSDimitry Andric PythonBytes::PythonBytes(llvm::ArrayRef<uint8_t> bytes) { SetBytes(bytes); }
2940b57cec5SDimitry Andric 
2959dba64beSDimitry Andric PythonBytes::PythonBytes(const uint8_t *bytes, size_t length) {
2960b57cec5SDimitry Andric   SetBytes(llvm::ArrayRef<uint8_t>(bytes, length));
2970b57cec5SDimitry Andric }
2980b57cec5SDimitry Andric 
2990b57cec5SDimitry Andric bool PythonBytes::Check(PyObject *py_obj) {
3000b57cec5SDimitry Andric   if (!py_obj)
3010b57cec5SDimitry Andric     return false;
3020b57cec5SDimitry Andric   return PyBytes_Check(py_obj);
3030b57cec5SDimitry Andric }
3040b57cec5SDimitry Andric 
3050b57cec5SDimitry Andric llvm::ArrayRef<uint8_t> PythonBytes::GetBytes() const {
3060b57cec5SDimitry Andric   if (!IsValid())
3070b57cec5SDimitry Andric     return llvm::ArrayRef<uint8_t>();
3080b57cec5SDimitry Andric 
3090b57cec5SDimitry Andric   Py_ssize_t size;
3100b57cec5SDimitry Andric   char *c;
3110b57cec5SDimitry Andric 
3120b57cec5SDimitry Andric   PyBytes_AsStringAndSize(m_py_obj, &c, &size);
3130b57cec5SDimitry Andric   return llvm::ArrayRef<uint8_t>(reinterpret_cast<uint8_t *>(c), size);
3140b57cec5SDimitry Andric }
3150b57cec5SDimitry Andric 
3160b57cec5SDimitry Andric size_t PythonBytes::GetSize() const {
3170b57cec5SDimitry Andric   if (!IsValid())
3180b57cec5SDimitry Andric     return 0;
3190b57cec5SDimitry Andric   return PyBytes_Size(m_py_obj);
3200b57cec5SDimitry Andric }
3210b57cec5SDimitry Andric 
3220b57cec5SDimitry Andric void PythonBytes::SetBytes(llvm::ArrayRef<uint8_t> bytes) {
3230b57cec5SDimitry Andric   const char *data = reinterpret_cast<const char *>(bytes.data());
3249dba64beSDimitry Andric   *this = Take<PythonBytes>(PyBytes_FromStringAndSize(data, bytes.size()));
3250b57cec5SDimitry Andric }
3260b57cec5SDimitry Andric 
3270b57cec5SDimitry Andric StructuredData::StringSP PythonBytes::CreateStructuredString() const {
3280b57cec5SDimitry Andric   StructuredData::StringSP result(new StructuredData::String);
3290b57cec5SDimitry Andric   Py_ssize_t size;
3300b57cec5SDimitry Andric   char *c;
3310b57cec5SDimitry Andric   PyBytes_AsStringAndSize(m_py_obj, &c, &size);
3320b57cec5SDimitry Andric   result->SetValue(std::string(c, size));
3330b57cec5SDimitry Andric   return result;
3340b57cec5SDimitry Andric }
3350b57cec5SDimitry Andric 
3360b57cec5SDimitry Andric PythonByteArray::PythonByteArray(llvm::ArrayRef<uint8_t> bytes)
3370b57cec5SDimitry Andric     : PythonByteArray(bytes.data(), bytes.size()) {}
3380b57cec5SDimitry Andric 
3390b57cec5SDimitry Andric PythonByteArray::PythonByteArray(const uint8_t *bytes, size_t length) {
3400b57cec5SDimitry Andric   const char *str = reinterpret_cast<const char *>(bytes);
3419dba64beSDimitry Andric   *this = Take<PythonByteArray>(PyByteArray_FromStringAndSize(str, length));
3420b57cec5SDimitry Andric }
3430b57cec5SDimitry Andric 
3440b57cec5SDimitry Andric bool PythonByteArray::Check(PyObject *py_obj) {
3450b57cec5SDimitry Andric   if (!py_obj)
3460b57cec5SDimitry Andric     return false;
3470b57cec5SDimitry Andric   return PyByteArray_Check(py_obj);
3480b57cec5SDimitry Andric }
3490b57cec5SDimitry Andric 
3500b57cec5SDimitry Andric llvm::ArrayRef<uint8_t> PythonByteArray::GetBytes() const {
3510b57cec5SDimitry Andric   if (!IsValid())
3520b57cec5SDimitry Andric     return llvm::ArrayRef<uint8_t>();
3530b57cec5SDimitry Andric 
3540b57cec5SDimitry Andric   char *c = PyByteArray_AsString(m_py_obj);
3550b57cec5SDimitry Andric   size_t size = GetSize();
3560b57cec5SDimitry Andric   return llvm::ArrayRef<uint8_t>(reinterpret_cast<uint8_t *>(c), size);
3570b57cec5SDimitry Andric }
3580b57cec5SDimitry Andric 
3590b57cec5SDimitry Andric size_t PythonByteArray::GetSize() const {
3600b57cec5SDimitry Andric   if (!IsValid())
3610b57cec5SDimitry Andric     return 0;
3620b57cec5SDimitry Andric 
3630b57cec5SDimitry Andric   return PyByteArray_Size(m_py_obj);
3640b57cec5SDimitry Andric }
3650b57cec5SDimitry Andric 
3660b57cec5SDimitry Andric StructuredData::StringSP PythonByteArray::CreateStructuredString() const {
3670b57cec5SDimitry Andric   StructuredData::StringSP result(new StructuredData::String);
3680b57cec5SDimitry Andric   llvm::ArrayRef<uint8_t> bytes = GetBytes();
3690b57cec5SDimitry Andric   const char *str = reinterpret_cast<const char *>(bytes.data());
3700b57cec5SDimitry Andric   result->SetValue(std::string(str, bytes.size()));
3710b57cec5SDimitry Andric   return result;
3720b57cec5SDimitry Andric }
3730b57cec5SDimitry Andric 
3740b57cec5SDimitry Andric // PythonString
3750b57cec5SDimitry Andric 
3769dba64beSDimitry Andric Expected<PythonString> PythonString::FromUTF8(llvm::StringRef string) {
3779dba64beSDimitry Andric   PyObject *str = PyUnicode_FromStringAndSize(string.data(), string.size());
3789dba64beSDimitry Andric   if (!str)
3799dba64beSDimitry Andric     return llvm::make_error<PythonException>();
3809dba64beSDimitry Andric   return Take<PythonString>(str);
3810b57cec5SDimitry Andric }
3820b57cec5SDimitry Andric 
3839dba64beSDimitry Andric PythonString::PythonString(llvm::StringRef string) { SetString(string); }
3840b57cec5SDimitry Andric 
3850b57cec5SDimitry Andric bool PythonString::Check(PyObject *py_obj) {
3860b57cec5SDimitry Andric   if (!py_obj)
3870b57cec5SDimitry Andric     return false;
3880b57cec5SDimitry Andric 
3890b57cec5SDimitry Andric   if (PyUnicode_Check(py_obj))
3900b57cec5SDimitry Andric     return true;
3910b57cec5SDimitry Andric   return false;
3920b57cec5SDimitry Andric }
3930b57cec5SDimitry Andric 
3940b57cec5SDimitry Andric llvm::StringRef PythonString::GetString() const {
3959dba64beSDimitry Andric   auto s = AsUTF8();
3969dba64beSDimitry Andric   if (!s) {
3979dba64beSDimitry Andric     llvm::consumeError(s.takeError());
3989dba64beSDimitry Andric     return llvm::StringRef("");
3999dba64beSDimitry Andric   }
4009dba64beSDimitry Andric   return s.get();
4019dba64beSDimitry Andric }
4029dba64beSDimitry Andric 
4039dba64beSDimitry Andric Expected<llvm::StringRef> PythonString::AsUTF8() const {
4040b57cec5SDimitry Andric   if (!IsValid())
4059dba64beSDimitry Andric     return nullDeref();
4060b57cec5SDimitry Andric 
4070b57cec5SDimitry Andric   Py_ssize_t size;
4080b57cec5SDimitry Andric   const char *data;
4090b57cec5SDimitry Andric 
4100b57cec5SDimitry Andric   data = PyUnicode_AsUTF8AndSize(m_py_obj, &size);
4119dba64beSDimitry Andric 
4129dba64beSDimitry Andric   if (!data)
4139dba64beSDimitry Andric     return exception();
4149dba64beSDimitry Andric 
4150b57cec5SDimitry Andric   return llvm::StringRef(data, size);
4160b57cec5SDimitry Andric }
4170b57cec5SDimitry Andric 
4180b57cec5SDimitry Andric size_t PythonString::GetSize() const {
4190b57cec5SDimitry Andric   if (IsValid()) {
420e8d8bef9SDimitry Andric #if PY_MINOR_VERSION >= 3
421e8d8bef9SDimitry Andric     return PyUnicode_GetLength(m_py_obj);
422e8d8bef9SDimitry Andric #else
4230b57cec5SDimitry Andric     return PyUnicode_GetSize(m_py_obj);
424e8d8bef9SDimitry Andric #endif
4250b57cec5SDimitry Andric   }
4260b57cec5SDimitry Andric   return 0;
4270b57cec5SDimitry Andric }
4280b57cec5SDimitry Andric 
4290b57cec5SDimitry Andric void PythonString::SetString(llvm::StringRef string) {
4309dba64beSDimitry Andric   auto s = FromUTF8(string);
4319dba64beSDimitry Andric   if (!s) {
4329dba64beSDimitry Andric     llvm::consumeError(s.takeError());
4339dba64beSDimitry Andric     Reset();
4349dba64beSDimitry Andric   } else {
4359dba64beSDimitry Andric     *this = std::move(s.get());
4369dba64beSDimitry Andric   }
4370b57cec5SDimitry Andric }
4380b57cec5SDimitry Andric 
4390b57cec5SDimitry Andric StructuredData::StringSP PythonString::CreateStructuredString() const {
4400b57cec5SDimitry Andric   StructuredData::StringSP result(new StructuredData::String);
4410b57cec5SDimitry Andric   result->SetValue(GetString());
4420b57cec5SDimitry Andric   return result;
4430b57cec5SDimitry Andric }
4440b57cec5SDimitry Andric 
4450b57cec5SDimitry Andric // PythonInteger
4460b57cec5SDimitry Andric 
4479dba64beSDimitry Andric PythonInteger::PythonInteger(int64_t value) { SetInteger(value); }
4480b57cec5SDimitry Andric 
4490b57cec5SDimitry Andric bool PythonInteger::Check(PyObject *py_obj) {
4500b57cec5SDimitry Andric   if (!py_obj)
4510b57cec5SDimitry Andric     return false;
4520b57cec5SDimitry Andric 
4530b57cec5SDimitry Andric   // Python 3 does not have PyInt_Check.  There is only one type of integral
4540b57cec5SDimitry Andric   // value, long.
4550b57cec5SDimitry Andric   return PyLong_Check(py_obj);
4560b57cec5SDimitry Andric }
4570b57cec5SDimitry Andric 
4580b57cec5SDimitry Andric void PythonInteger::SetInteger(int64_t value) {
4599dba64beSDimitry Andric   *this = Take<PythonInteger>(PyLong_FromLongLong(value));
4600b57cec5SDimitry Andric }
4610b57cec5SDimitry Andric 
4620b57cec5SDimitry Andric StructuredData::IntegerSP PythonInteger::CreateStructuredInteger() const {
4630b57cec5SDimitry Andric   StructuredData::IntegerSP result(new StructuredData::Integer);
4645ffd83dbSDimitry Andric   // FIXME this is really not ideal.   Errors are silently converted to 0
4655ffd83dbSDimitry Andric   // and overflows are silently wrapped.   But we'd need larger changes
4665ffd83dbSDimitry Andric   // to StructuredData to fix it, so that's how it is for now.
4675ffd83dbSDimitry Andric   llvm::Expected<unsigned long long> value = AsModuloUnsignedLongLong();
4685ffd83dbSDimitry Andric   if (!value) {
4695ffd83dbSDimitry Andric     llvm::consumeError(value.takeError());
4705ffd83dbSDimitry Andric     result->SetValue(0);
4715ffd83dbSDimitry Andric   } else {
4725ffd83dbSDimitry Andric     result->SetValue(value.get());
4735ffd83dbSDimitry Andric   }
4740b57cec5SDimitry Andric   return result;
4750b57cec5SDimitry Andric }
4760b57cec5SDimitry Andric 
4770b57cec5SDimitry Andric // PythonBoolean
4780b57cec5SDimitry Andric 
4790b57cec5SDimitry Andric PythonBoolean::PythonBoolean(bool value) {
4800b57cec5SDimitry Andric   SetValue(value);
4810b57cec5SDimitry Andric }
4820b57cec5SDimitry Andric 
4830b57cec5SDimitry Andric bool PythonBoolean::Check(PyObject *py_obj) {
4840b57cec5SDimitry Andric   return py_obj ? PyBool_Check(py_obj) : false;
4850b57cec5SDimitry Andric }
4860b57cec5SDimitry Andric 
4870b57cec5SDimitry Andric bool PythonBoolean::GetValue() const {
4880b57cec5SDimitry Andric   return m_py_obj ? PyObject_IsTrue(m_py_obj) : false;
4890b57cec5SDimitry Andric }
4900b57cec5SDimitry Andric 
4910b57cec5SDimitry Andric void PythonBoolean::SetValue(bool value) {
4929dba64beSDimitry Andric   *this = Take<PythonBoolean>(PyBool_FromLong(value));
4930b57cec5SDimitry Andric }
4940b57cec5SDimitry Andric 
4950b57cec5SDimitry Andric StructuredData::BooleanSP PythonBoolean::CreateStructuredBoolean() const {
4960b57cec5SDimitry Andric   StructuredData::BooleanSP result(new StructuredData::Boolean);
4970b57cec5SDimitry Andric   result->SetValue(GetValue());
4980b57cec5SDimitry Andric   return result;
4990b57cec5SDimitry Andric }
5000b57cec5SDimitry Andric 
5010b57cec5SDimitry Andric // PythonList
5020b57cec5SDimitry Andric 
5039dba64beSDimitry Andric PythonList::PythonList(PyInitialValue value) {
5040b57cec5SDimitry Andric   if (value == PyInitialValue::Empty)
5059dba64beSDimitry Andric     *this = Take<PythonList>(PyList_New(0));
5060b57cec5SDimitry Andric }
5070b57cec5SDimitry Andric 
5089dba64beSDimitry Andric PythonList::PythonList(int list_size) {
5099dba64beSDimitry Andric   *this = Take<PythonList>(PyList_New(list_size));
5100b57cec5SDimitry Andric }
5110b57cec5SDimitry Andric 
5120b57cec5SDimitry Andric bool PythonList::Check(PyObject *py_obj) {
5130b57cec5SDimitry Andric   if (!py_obj)
5140b57cec5SDimitry Andric     return false;
5150b57cec5SDimitry Andric   return PyList_Check(py_obj);
5160b57cec5SDimitry Andric }
5170b57cec5SDimitry Andric 
5180b57cec5SDimitry Andric uint32_t PythonList::GetSize() const {
5190b57cec5SDimitry Andric   if (IsValid())
5200b57cec5SDimitry Andric     return PyList_GET_SIZE(m_py_obj);
5210b57cec5SDimitry Andric   return 0;
5220b57cec5SDimitry Andric }
5230b57cec5SDimitry Andric 
5240b57cec5SDimitry Andric PythonObject PythonList::GetItemAtIndex(uint32_t index) const {
5250b57cec5SDimitry Andric   if (IsValid())
5260b57cec5SDimitry Andric     return PythonObject(PyRefType::Borrowed, PyList_GetItem(m_py_obj, index));
5270b57cec5SDimitry Andric   return PythonObject();
5280b57cec5SDimitry Andric }
5290b57cec5SDimitry Andric 
5300b57cec5SDimitry Andric void PythonList::SetItemAtIndex(uint32_t index, const PythonObject &object) {
5310b57cec5SDimitry Andric   if (IsAllocated() && object.IsValid()) {
5320b57cec5SDimitry Andric     // PyList_SetItem is documented to "steal" a reference, so we need to
5330b57cec5SDimitry Andric     // convert it to an owned reference by incrementing it.
5340b57cec5SDimitry Andric     Py_INCREF(object.get());
5350b57cec5SDimitry Andric     PyList_SetItem(m_py_obj, index, object.get());
5360b57cec5SDimitry Andric   }
5370b57cec5SDimitry Andric }
5380b57cec5SDimitry Andric 
5390b57cec5SDimitry Andric void PythonList::AppendItem(const PythonObject &object) {
5400b57cec5SDimitry Andric   if (IsAllocated() && object.IsValid()) {
5410b57cec5SDimitry Andric     // `PyList_Append` does *not* steal a reference, so do not call `Py_INCREF`
5420b57cec5SDimitry Andric     // here like we do with `PyList_SetItem`.
5430b57cec5SDimitry Andric     PyList_Append(m_py_obj, object.get());
5440b57cec5SDimitry Andric   }
5450b57cec5SDimitry Andric }
5460b57cec5SDimitry Andric 
5470b57cec5SDimitry Andric StructuredData::ArraySP PythonList::CreateStructuredArray() const {
5480b57cec5SDimitry Andric   StructuredData::ArraySP result(new StructuredData::Array);
5490b57cec5SDimitry Andric   uint32_t count = GetSize();
5500b57cec5SDimitry Andric   for (uint32_t i = 0; i < count; ++i) {
5510b57cec5SDimitry Andric     PythonObject obj = GetItemAtIndex(i);
5520b57cec5SDimitry Andric     result->AddItem(obj.CreateStructuredObject());
5530b57cec5SDimitry Andric   }
5540b57cec5SDimitry Andric   return result;
5550b57cec5SDimitry Andric }
5560b57cec5SDimitry Andric 
5570b57cec5SDimitry Andric // PythonTuple
5580b57cec5SDimitry Andric 
5599dba64beSDimitry Andric PythonTuple::PythonTuple(PyInitialValue value) {
5600b57cec5SDimitry Andric   if (value == PyInitialValue::Empty)
5619dba64beSDimitry Andric     *this = Take<PythonTuple>(PyTuple_New(0));
5620b57cec5SDimitry Andric }
5630b57cec5SDimitry Andric 
5649dba64beSDimitry Andric PythonTuple::PythonTuple(int tuple_size) {
5659dba64beSDimitry Andric   *this = Take<PythonTuple>(PyTuple_New(tuple_size));
5660b57cec5SDimitry Andric }
5670b57cec5SDimitry Andric 
5680b57cec5SDimitry Andric PythonTuple::PythonTuple(std::initializer_list<PythonObject> objects) {
5690b57cec5SDimitry Andric   m_py_obj = PyTuple_New(objects.size());
5700b57cec5SDimitry Andric 
5710b57cec5SDimitry Andric   uint32_t idx = 0;
5720b57cec5SDimitry Andric   for (auto object : objects) {
5730b57cec5SDimitry Andric     if (object.IsValid())
5740b57cec5SDimitry Andric       SetItemAtIndex(idx, object);
5750b57cec5SDimitry Andric     idx++;
5760b57cec5SDimitry Andric   }
5770b57cec5SDimitry Andric }
5780b57cec5SDimitry Andric 
5790b57cec5SDimitry Andric PythonTuple::PythonTuple(std::initializer_list<PyObject *> objects) {
5800b57cec5SDimitry Andric   m_py_obj = PyTuple_New(objects.size());
5810b57cec5SDimitry Andric 
5820b57cec5SDimitry Andric   uint32_t idx = 0;
5830b57cec5SDimitry Andric   for (auto py_object : objects) {
5840b57cec5SDimitry Andric     PythonObject object(PyRefType::Borrowed, py_object);
5850b57cec5SDimitry Andric     if (object.IsValid())
5860b57cec5SDimitry Andric       SetItemAtIndex(idx, object);
5870b57cec5SDimitry Andric     idx++;
5880b57cec5SDimitry Andric   }
5890b57cec5SDimitry Andric }
5900b57cec5SDimitry Andric 
5910b57cec5SDimitry Andric bool PythonTuple::Check(PyObject *py_obj) {
5920b57cec5SDimitry Andric   if (!py_obj)
5930b57cec5SDimitry Andric     return false;
5940b57cec5SDimitry Andric   return PyTuple_Check(py_obj);
5950b57cec5SDimitry Andric }
5960b57cec5SDimitry Andric 
5970b57cec5SDimitry Andric uint32_t PythonTuple::GetSize() const {
5980b57cec5SDimitry Andric   if (IsValid())
5990b57cec5SDimitry Andric     return PyTuple_GET_SIZE(m_py_obj);
6000b57cec5SDimitry Andric   return 0;
6010b57cec5SDimitry Andric }
6020b57cec5SDimitry Andric 
6030b57cec5SDimitry Andric PythonObject PythonTuple::GetItemAtIndex(uint32_t index) const {
6040b57cec5SDimitry Andric   if (IsValid())
6050b57cec5SDimitry Andric     return PythonObject(PyRefType::Borrowed, PyTuple_GetItem(m_py_obj, index));
6060b57cec5SDimitry Andric   return PythonObject();
6070b57cec5SDimitry Andric }
6080b57cec5SDimitry Andric 
6090b57cec5SDimitry Andric void PythonTuple::SetItemAtIndex(uint32_t index, const PythonObject &object) {
6100b57cec5SDimitry Andric   if (IsAllocated() && object.IsValid()) {
6110b57cec5SDimitry Andric     // PyTuple_SetItem is documented to "steal" a reference, so we need to
6120b57cec5SDimitry Andric     // convert it to an owned reference by incrementing it.
6130b57cec5SDimitry Andric     Py_INCREF(object.get());
6140b57cec5SDimitry Andric     PyTuple_SetItem(m_py_obj, index, object.get());
6150b57cec5SDimitry Andric   }
6160b57cec5SDimitry Andric }
6170b57cec5SDimitry Andric 
6180b57cec5SDimitry Andric StructuredData::ArraySP PythonTuple::CreateStructuredArray() const {
6190b57cec5SDimitry Andric   StructuredData::ArraySP result(new StructuredData::Array);
6200b57cec5SDimitry Andric   uint32_t count = GetSize();
6210b57cec5SDimitry Andric   for (uint32_t i = 0; i < count; ++i) {
6220b57cec5SDimitry Andric     PythonObject obj = GetItemAtIndex(i);
6230b57cec5SDimitry Andric     result->AddItem(obj.CreateStructuredObject());
6240b57cec5SDimitry Andric   }
6250b57cec5SDimitry Andric   return result;
6260b57cec5SDimitry Andric }
6270b57cec5SDimitry Andric 
6280b57cec5SDimitry Andric // PythonDictionary
6290b57cec5SDimitry Andric 
6309dba64beSDimitry Andric PythonDictionary::PythonDictionary(PyInitialValue value) {
6310b57cec5SDimitry Andric   if (value == PyInitialValue::Empty)
6329dba64beSDimitry Andric     *this = Take<PythonDictionary>(PyDict_New());
6330b57cec5SDimitry Andric }
6340b57cec5SDimitry Andric 
6350b57cec5SDimitry Andric bool PythonDictionary::Check(PyObject *py_obj) {
6360b57cec5SDimitry Andric   if (!py_obj)
6370b57cec5SDimitry Andric     return false;
6380b57cec5SDimitry Andric 
6390b57cec5SDimitry Andric   return PyDict_Check(py_obj);
6400b57cec5SDimitry Andric }
6410b57cec5SDimitry Andric 
6420b57cec5SDimitry Andric uint32_t PythonDictionary::GetSize() const {
6430b57cec5SDimitry Andric   if (IsValid())
6440b57cec5SDimitry Andric     return PyDict_Size(m_py_obj);
6450b57cec5SDimitry Andric   return 0;
6460b57cec5SDimitry Andric }
6470b57cec5SDimitry Andric 
6480b57cec5SDimitry Andric PythonList PythonDictionary::GetKeys() const {
6490b57cec5SDimitry Andric   if (IsValid())
6500b57cec5SDimitry Andric     return PythonList(PyRefType::Owned, PyDict_Keys(m_py_obj));
6510b57cec5SDimitry Andric   return PythonList(PyInitialValue::Invalid);
6520b57cec5SDimitry Andric }
6530b57cec5SDimitry Andric 
6540b57cec5SDimitry Andric PythonObject PythonDictionary::GetItemForKey(const PythonObject &key) const {
6559dba64beSDimitry Andric   auto item = GetItem(key);
6569dba64beSDimitry Andric   if (!item) {
6579dba64beSDimitry Andric     llvm::consumeError(item.takeError());
6580b57cec5SDimitry Andric     return PythonObject();
6590b57cec5SDimitry Andric   }
6609dba64beSDimitry Andric   return std::move(item.get());
6619dba64beSDimitry Andric }
6629dba64beSDimitry Andric 
6639dba64beSDimitry Andric Expected<PythonObject>
6649dba64beSDimitry Andric PythonDictionary::GetItem(const PythonObject &key) const {
6659dba64beSDimitry Andric   if (!IsValid())
6669dba64beSDimitry Andric     return nullDeref();
6679dba64beSDimitry Andric   PyObject *o = PyDict_GetItemWithError(m_py_obj, key.get());
6689dba64beSDimitry Andric   if (PyErr_Occurred())
6699dba64beSDimitry Andric     return exception();
6709dba64beSDimitry Andric   if (!o)
6719dba64beSDimitry Andric     return keyError();
6729dba64beSDimitry Andric   return Retain<PythonObject>(o);
6739dba64beSDimitry Andric }
6749dba64beSDimitry Andric 
6759dba64beSDimitry Andric Expected<PythonObject> PythonDictionary::GetItem(const Twine &key) const {
6769dba64beSDimitry Andric   if (!IsValid())
6779dba64beSDimitry Andric     return nullDeref();
6789dba64beSDimitry Andric   PyObject *o = PyDict_GetItemString(m_py_obj, NullTerminated(key));
6799dba64beSDimitry Andric   if (PyErr_Occurred())
6809dba64beSDimitry Andric     return exception();
6819dba64beSDimitry Andric   if (!o)
6829dba64beSDimitry Andric     return keyError();
6839dba64beSDimitry Andric   return Retain<PythonObject>(o);
6849dba64beSDimitry Andric }
6859dba64beSDimitry Andric 
6869dba64beSDimitry Andric Error PythonDictionary::SetItem(const PythonObject &key,
6879dba64beSDimitry Andric                                 const PythonObject &value) const {
6889dba64beSDimitry Andric   if (!IsValid() || !value.IsValid())
6899dba64beSDimitry Andric     return nullDeref();
6909dba64beSDimitry Andric   int r = PyDict_SetItem(m_py_obj, key.get(), value.get());
6919dba64beSDimitry Andric   if (r < 0)
6929dba64beSDimitry Andric     return exception();
6939dba64beSDimitry Andric   return Error::success();
6949dba64beSDimitry Andric }
6959dba64beSDimitry Andric 
6969dba64beSDimitry Andric Error PythonDictionary::SetItem(const Twine &key,
6979dba64beSDimitry Andric                                 const PythonObject &value) const {
6989dba64beSDimitry Andric   if (!IsValid() || !value.IsValid())
6999dba64beSDimitry Andric     return nullDeref();
7009dba64beSDimitry Andric   int r = PyDict_SetItemString(m_py_obj, NullTerminated(key), value.get());
7019dba64beSDimitry Andric   if (r < 0)
7029dba64beSDimitry Andric     return exception();
7039dba64beSDimitry Andric   return Error::success();
7049dba64beSDimitry Andric }
7050b57cec5SDimitry Andric 
7060b57cec5SDimitry Andric void PythonDictionary::SetItemForKey(const PythonObject &key,
7070b57cec5SDimitry Andric                                      const PythonObject &value) {
7089dba64beSDimitry Andric   Error error = SetItem(key, value);
7099dba64beSDimitry Andric   if (error)
7109dba64beSDimitry Andric     llvm::consumeError(std::move(error));
7110b57cec5SDimitry Andric }
7120b57cec5SDimitry Andric 
7130b57cec5SDimitry Andric StructuredData::DictionarySP
7140b57cec5SDimitry Andric PythonDictionary::CreateStructuredDictionary() const {
7150b57cec5SDimitry Andric   StructuredData::DictionarySP result(new StructuredData::Dictionary);
7160b57cec5SDimitry Andric   PythonList keys(GetKeys());
7170b57cec5SDimitry Andric   uint32_t num_keys = keys.GetSize();
7180b57cec5SDimitry Andric   for (uint32_t i = 0; i < num_keys; ++i) {
7190b57cec5SDimitry Andric     PythonObject key = keys.GetItemAtIndex(i);
7200b57cec5SDimitry Andric     PythonObject value = GetItemForKey(key);
7210b57cec5SDimitry Andric     StructuredData::ObjectSP structured_value = value.CreateStructuredObject();
7220b57cec5SDimitry Andric     result->AddItem(key.Str().GetString(), structured_value);
7230b57cec5SDimitry Andric   }
7240b57cec5SDimitry Andric   return result;
7250b57cec5SDimitry Andric }
7260b57cec5SDimitry Andric 
727*81ad6265SDimitry Andric PythonModule PythonModule::BuiltinsModule() { return AddModule("builtins"); }
7280b57cec5SDimitry Andric 
7290b57cec5SDimitry Andric PythonModule PythonModule::MainModule() { return AddModule("__main__"); }
7300b57cec5SDimitry Andric 
7310b57cec5SDimitry Andric PythonModule PythonModule::AddModule(llvm::StringRef module) {
7320b57cec5SDimitry Andric   std::string str = module.str();
7330b57cec5SDimitry Andric   return PythonModule(PyRefType::Borrowed, PyImport_AddModule(str.c_str()));
7340b57cec5SDimitry Andric }
7350b57cec5SDimitry Andric 
7369dba64beSDimitry Andric Expected<PythonModule> PythonModule::Import(const Twine &name) {
7379dba64beSDimitry Andric   PyObject *mod = PyImport_ImportModule(NullTerminated(name));
7389dba64beSDimitry Andric   if (!mod)
7399dba64beSDimitry Andric     return exception();
7409dba64beSDimitry Andric   return Take<PythonModule>(mod);
7419dba64beSDimitry Andric }
7429dba64beSDimitry Andric 
7439dba64beSDimitry Andric Expected<PythonObject> PythonModule::Get(const Twine &name) {
7449dba64beSDimitry Andric   if (!IsValid())
7459dba64beSDimitry Andric     return nullDeref();
7469dba64beSDimitry Andric   PyObject *dict = PyModule_GetDict(m_py_obj);
7479dba64beSDimitry Andric   if (!dict)
7489dba64beSDimitry Andric     return exception();
7499dba64beSDimitry Andric   PyObject *item = PyDict_GetItemString(dict, NullTerminated(name));
7509dba64beSDimitry Andric   if (!item)
7519dba64beSDimitry Andric     return exception();
7529dba64beSDimitry Andric   return Retain<PythonObject>(item);
7530b57cec5SDimitry Andric }
7540b57cec5SDimitry Andric 
7550b57cec5SDimitry Andric bool PythonModule::Check(PyObject *py_obj) {
7560b57cec5SDimitry Andric   if (!py_obj)
7570b57cec5SDimitry Andric     return false;
7580b57cec5SDimitry Andric 
7590b57cec5SDimitry Andric   return PyModule_Check(py_obj);
7600b57cec5SDimitry Andric }
7610b57cec5SDimitry Andric 
7620b57cec5SDimitry Andric PythonDictionary PythonModule::GetDictionary() const {
7639dba64beSDimitry Andric   if (!IsValid())
7649dba64beSDimitry Andric     return PythonDictionary();
7659dba64beSDimitry Andric   return Retain<PythonDictionary>(PyModule_GetDict(m_py_obj));
7660b57cec5SDimitry Andric }
7670b57cec5SDimitry Andric 
7680b57cec5SDimitry Andric bool PythonCallable::Check(PyObject *py_obj) {
7690b57cec5SDimitry Andric   if (!py_obj)
7700b57cec5SDimitry Andric     return false;
7710b57cec5SDimitry Andric 
7720b57cec5SDimitry Andric   return PyCallable_Check(py_obj);
7730b57cec5SDimitry Andric }
7740b57cec5SDimitry Andric 
7759dba64beSDimitry Andric #if PY_MAJOR_VERSION >= 3 && PY_MINOR_VERSION >= 3
7769dba64beSDimitry Andric static const char get_arg_info_script[] = R"(
7779dba64beSDimitry Andric from inspect import signature, Parameter, ismethod
7789dba64beSDimitry Andric from collections import namedtuple
779480093f4SDimitry Andric ArgInfo = namedtuple('ArgInfo', ['count', 'has_varargs'])
7809dba64beSDimitry Andric def main(f):
7819dba64beSDimitry Andric     count = 0
7829dba64beSDimitry Andric     varargs = False
7839dba64beSDimitry Andric     for parameter in signature(f).parameters.values():
7849dba64beSDimitry Andric         kind = parameter.kind
7859dba64beSDimitry Andric         if kind in (Parameter.POSITIONAL_ONLY,
7869dba64beSDimitry Andric                     Parameter.POSITIONAL_OR_KEYWORD):
7879dba64beSDimitry Andric             count += 1
7889dba64beSDimitry Andric         elif kind == Parameter.VAR_POSITIONAL:
7899dba64beSDimitry Andric             varargs = True
7909dba64beSDimitry Andric         elif kind in (Parameter.KEYWORD_ONLY,
7919dba64beSDimitry Andric                       Parameter.VAR_KEYWORD):
7929dba64beSDimitry Andric             pass
7939dba64beSDimitry Andric         else:
7949dba64beSDimitry Andric             raise Exception(f'unknown parameter kind: {kind}')
795480093f4SDimitry Andric     return ArgInfo(count, varargs)
7969dba64beSDimitry Andric )";
7979dba64beSDimitry Andric #endif
7989dba64beSDimitry Andric 
7999dba64beSDimitry Andric Expected<PythonCallable::ArgInfo> PythonCallable::GetArgInfo() const {
8009dba64beSDimitry Andric   ArgInfo result = {};
8019dba64beSDimitry Andric   if (!IsValid())
8029dba64beSDimitry Andric     return nullDeref();
8039dba64beSDimitry Andric 
8049dba64beSDimitry Andric #if PY_MAJOR_VERSION >= 3 && PY_MINOR_VERSION >= 3
8059dba64beSDimitry Andric 
8069dba64beSDimitry Andric   // no need to synchronize access to this global, we already have the GIL
8079dba64beSDimitry Andric   static PythonScript get_arg_info(get_arg_info_script);
8089dba64beSDimitry Andric   Expected<PythonObject> pyarginfo = get_arg_info(*this);
8099dba64beSDimitry Andric   if (!pyarginfo)
8109dba64beSDimitry Andric     return pyarginfo.takeError();
811480093f4SDimitry Andric   long long count =
812480093f4SDimitry Andric       cantFail(As<long long>(pyarginfo.get().GetAttribute("count")));
813480093f4SDimitry Andric   bool has_varargs =
8149dba64beSDimitry Andric       cantFail(As<bool>(pyarginfo.get().GetAttribute("has_varargs")));
815480093f4SDimitry Andric   result.max_positional_args = has_varargs ? ArgInfo::UNBOUNDED : count;
8169dba64beSDimitry Andric 
8179dba64beSDimitry Andric #else
818480093f4SDimitry Andric   PyObject *py_func_obj;
8199dba64beSDimitry Andric   bool is_bound_method = false;
820480093f4SDimitry Andric   bool is_class = false;
821480093f4SDimitry Andric 
822480093f4SDimitry Andric   if (PyType_Check(m_py_obj) || PyClass_Check(m_py_obj)) {
823480093f4SDimitry Andric     auto init = GetAttribute("__init__");
824480093f4SDimitry Andric     if (!init)
825480093f4SDimitry Andric       return init.takeError();
826480093f4SDimitry Andric     py_func_obj = init.get().get();
827480093f4SDimitry Andric     is_class = true;
828480093f4SDimitry Andric   } else {
829480093f4SDimitry Andric     py_func_obj = m_py_obj;
830480093f4SDimitry Andric   }
831480093f4SDimitry Andric 
8320b57cec5SDimitry Andric   if (PyMethod_Check(py_func_obj)) {
8330b57cec5SDimitry Andric     py_func_obj = PyMethod_GET_FUNCTION(py_func_obj);
8340b57cec5SDimitry Andric     PythonObject im_self = GetAttributeValue("im_self");
8350b57cec5SDimitry Andric     if (im_self.IsValid() && !im_self.IsNone())
8369dba64beSDimitry Andric       is_bound_method = true;
8370b57cec5SDimitry Andric   } else {
8380b57cec5SDimitry Andric     // see if this is a callable object with an __call__ method
8390b57cec5SDimitry Andric     if (!PyFunction_Check(py_func_obj)) {
8400b57cec5SDimitry Andric       PythonObject __call__ = GetAttributeValue("__call__");
8410b57cec5SDimitry Andric       if (__call__.IsValid()) {
8420b57cec5SDimitry Andric         auto __callable__ = __call__.AsType<PythonCallable>();
8430b57cec5SDimitry Andric         if (__callable__.IsValid()) {
8440b57cec5SDimitry Andric           py_func_obj = PyMethod_GET_FUNCTION(__callable__.get());
8459dba64beSDimitry Andric           PythonObject im_self = __callable__.GetAttributeValue("im_self");
8460b57cec5SDimitry Andric           if (im_self.IsValid() && !im_self.IsNone())
8479dba64beSDimitry Andric             is_bound_method = true;
8480b57cec5SDimitry Andric         }
8490b57cec5SDimitry Andric       }
8500b57cec5SDimitry Andric     }
8510b57cec5SDimitry Andric   }
8520b57cec5SDimitry Andric 
8530b57cec5SDimitry Andric   if (!py_func_obj)
8540b57cec5SDimitry Andric     return result;
8550b57cec5SDimitry Andric 
8560b57cec5SDimitry Andric   PyCodeObject *code = (PyCodeObject *)PyFunction_GET_CODE(py_func_obj);
8570b57cec5SDimitry Andric   if (!code)
8580b57cec5SDimitry Andric     return result;
8590b57cec5SDimitry Andric 
860480093f4SDimitry Andric   auto count = code->co_argcount;
861480093f4SDimitry Andric   bool has_varargs = !!(code->co_flags & CO_VARARGS);
862480093f4SDimitry Andric   result.max_positional_args =
863480093f4SDimitry Andric       has_varargs ? ArgInfo::UNBOUNDED
864480093f4SDimitry Andric                   : (count - (int)is_bound_method) - (int)is_class;
8659dba64beSDimitry Andric 
8669dba64beSDimitry Andric #endif
8679dba64beSDimitry Andric 
8680b57cec5SDimitry Andric   return result;
8690b57cec5SDimitry Andric }
8700b57cec5SDimitry Andric 
8719dba64beSDimitry Andric constexpr unsigned
8729dba64beSDimitry Andric     PythonCallable::ArgInfo::UNBOUNDED; // FIXME delete after c++17
8739dba64beSDimitry Andric 
8740b57cec5SDimitry Andric PythonObject PythonCallable::operator()() {
8750b57cec5SDimitry Andric   return PythonObject(PyRefType::Owned, PyObject_CallObject(m_py_obj, nullptr));
8760b57cec5SDimitry Andric }
8770b57cec5SDimitry Andric 
8780b57cec5SDimitry Andric PythonObject PythonCallable::
8790b57cec5SDimitry Andric operator()(std::initializer_list<PyObject *> args) {
8800b57cec5SDimitry Andric   PythonTuple arg_tuple(args);
8810b57cec5SDimitry Andric   return PythonObject(PyRefType::Owned,
8820b57cec5SDimitry Andric                       PyObject_CallObject(m_py_obj, arg_tuple.get()));
8830b57cec5SDimitry Andric }
8840b57cec5SDimitry Andric 
8850b57cec5SDimitry Andric PythonObject PythonCallable::
8860b57cec5SDimitry Andric operator()(std::initializer_list<PythonObject> args) {
8870b57cec5SDimitry Andric   PythonTuple arg_tuple(args);
8880b57cec5SDimitry Andric   return PythonObject(PyRefType::Owned,
8890b57cec5SDimitry Andric                       PyObject_CallObject(m_py_obj, arg_tuple.get()));
8900b57cec5SDimitry Andric }
8910b57cec5SDimitry Andric 
8920b57cec5SDimitry Andric bool PythonFile::Check(PyObject *py_obj) {
8939dba64beSDimitry Andric   if (!py_obj)
8949dba64beSDimitry Andric     return false;
8950b57cec5SDimitry Andric   // In Python 3, there is no `PyFile_Check`, and in fact PyFile is not even a
8960b57cec5SDimitry Andric   // first-class object type anymore.  `PyFile_FromFd` is just a thin wrapper
8970b57cec5SDimitry Andric   // over `io.open()`, which returns some object derived from `io.IOBase`. As a
8980b57cec5SDimitry Andric   // result, the only way to detect a file in Python 3 is to check whether it
8999dba64beSDimitry Andric   // inherits from `io.IOBase`.
9009dba64beSDimitry Andric   auto io_module = PythonModule::Import("io");
9019dba64beSDimitry Andric   if (!io_module) {
9029dba64beSDimitry Andric     llvm::consumeError(io_module.takeError());
9030b57cec5SDimitry Andric     return false;
9049dba64beSDimitry Andric   }
9059dba64beSDimitry Andric   auto iobase = io_module.get().Get("IOBase");
9069dba64beSDimitry Andric   if (!iobase) {
9079dba64beSDimitry Andric     llvm::consumeError(iobase.takeError());
9080b57cec5SDimitry Andric     return false;
9099dba64beSDimitry Andric   }
9109dba64beSDimitry Andric   int r = PyObject_IsInstance(py_obj, iobase.get().get());
9119dba64beSDimitry Andric   if (r < 0) {
9129dba64beSDimitry Andric     llvm::consumeError(exception()); // clear the exception and log it.
9139dba64beSDimitry Andric     return false;
9149dba64beSDimitry Andric   }
9159dba64beSDimitry Andric   return !!r;
9160b57cec5SDimitry Andric }
9170b57cec5SDimitry Andric 
9189dba64beSDimitry Andric const char *PythonException::toCString() const {
9199dba64beSDimitry Andric   if (!m_repr_bytes)
9209dba64beSDimitry Andric     return "unknown exception";
9219dba64beSDimitry Andric   return PyBytes_AS_STRING(m_repr_bytes);
9220b57cec5SDimitry Andric }
9230b57cec5SDimitry Andric 
9249dba64beSDimitry Andric PythonException::PythonException(const char *caller) {
9259dba64beSDimitry Andric   assert(PyErr_Occurred());
9269dba64beSDimitry Andric   m_exception_type = m_exception = m_traceback = m_repr_bytes = NULL;
9279dba64beSDimitry Andric   PyErr_Fetch(&m_exception_type, &m_exception, &m_traceback);
9289dba64beSDimitry Andric   PyErr_NormalizeException(&m_exception_type, &m_exception, &m_traceback);
9299dba64beSDimitry Andric   PyErr_Clear();
9309dba64beSDimitry Andric   if (m_exception) {
9319dba64beSDimitry Andric     PyObject *repr = PyObject_Repr(m_exception);
9329dba64beSDimitry Andric     if (repr) {
9339dba64beSDimitry Andric       m_repr_bytes = PyUnicode_AsEncodedString(repr, "utf-8", nullptr);
9349dba64beSDimitry Andric       if (!m_repr_bytes) {
9359dba64beSDimitry Andric         PyErr_Clear();
9369dba64beSDimitry Andric       }
9379dba64beSDimitry Andric       Py_XDECREF(repr);
9389dba64beSDimitry Andric     } else {
9399dba64beSDimitry Andric       PyErr_Clear();
9409dba64beSDimitry Andric     }
9419dba64beSDimitry Andric   }
942*81ad6265SDimitry Andric   Log *log = GetLog(LLDBLog::Script);
9439dba64beSDimitry Andric   if (caller)
9449dba64beSDimitry Andric     LLDB_LOGF(log, "%s failed with exception: %s", caller, toCString());
9459dba64beSDimitry Andric   else
9469dba64beSDimitry Andric     LLDB_LOGF(log, "python exception: %s", toCString());
9479dba64beSDimitry Andric }
9489dba64beSDimitry Andric void PythonException::Restore() {
9499dba64beSDimitry Andric   if (m_exception_type && m_exception) {
9509dba64beSDimitry Andric     PyErr_Restore(m_exception_type, m_exception, m_traceback);
9519dba64beSDimitry Andric   } else {
9529dba64beSDimitry Andric     PyErr_SetString(PyExc_Exception, toCString());
9539dba64beSDimitry Andric   }
9549dba64beSDimitry Andric   m_exception_type = m_exception = m_traceback = NULL;
9550b57cec5SDimitry Andric }
9560b57cec5SDimitry Andric 
9579dba64beSDimitry Andric PythonException::~PythonException() {
9589dba64beSDimitry Andric   Py_XDECREF(m_exception_type);
9599dba64beSDimitry Andric   Py_XDECREF(m_exception);
9609dba64beSDimitry Andric   Py_XDECREF(m_traceback);
9619dba64beSDimitry Andric   Py_XDECREF(m_repr_bytes);
9620b57cec5SDimitry Andric }
9630b57cec5SDimitry Andric 
9649dba64beSDimitry Andric void PythonException::log(llvm::raw_ostream &OS) const { OS << toCString(); }
9659dba64beSDimitry Andric 
9669dba64beSDimitry Andric std::error_code PythonException::convertToErrorCode() const {
9679dba64beSDimitry Andric   return llvm::inconvertibleErrorCode();
9689dba64beSDimitry Andric }
9699dba64beSDimitry Andric 
9709dba64beSDimitry Andric bool PythonException::Matches(PyObject *exc) const {
9719dba64beSDimitry Andric   return PyErr_GivenExceptionMatches(m_exception_type, exc);
9729dba64beSDimitry Andric }
9739dba64beSDimitry Andric 
9749dba64beSDimitry Andric const char read_exception_script[] = R"(
9759dba64beSDimitry Andric import sys
9769dba64beSDimitry Andric from traceback import print_exception
9779dba64beSDimitry Andric if sys.version_info.major < 3:
9789dba64beSDimitry Andric   from StringIO import StringIO
9799dba64beSDimitry Andric else:
9809dba64beSDimitry Andric   from io import StringIO
9819dba64beSDimitry Andric def main(exc_type, exc_value, tb):
9829dba64beSDimitry Andric   f = StringIO()
9839dba64beSDimitry Andric   print_exception(exc_type, exc_value, tb, file=f)
9849dba64beSDimitry Andric   return f.getvalue()
9859dba64beSDimitry Andric )";
9869dba64beSDimitry Andric 
9879dba64beSDimitry Andric std::string PythonException::ReadBacktrace() const {
9889dba64beSDimitry Andric 
9899dba64beSDimitry Andric   if (!m_traceback)
9909dba64beSDimitry Andric     return toCString();
9919dba64beSDimitry Andric 
9929dba64beSDimitry Andric   // no need to synchronize access to this global, we already have the GIL
9939dba64beSDimitry Andric   static PythonScript read_exception(read_exception_script);
9949dba64beSDimitry Andric 
9959dba64beSDimitry Andric   Expected<std::string> backtrace = As<std::string>(
9969dba64beSDimitry Andric       read_exception(m_exception_type, m_exception, m_traceback));
9979dba64beSDimitry Andric 
9989dba64beSDimitry Andric   if (!backtrace) {
9999dba64beSDimitry Andric     std::string message =
10009dba64beSDimitry Andric         std::string(toCString()) + "\n" +
10015ffd83dbSDimitry Andric         "Traceback unavailable, an error occurred while reading it:\n";
10029dba64beSDimitry Andric     return (message + llvm::toString(backtrace.takeError()));
10039dba64beSDimitry Andric   }
10049dba64beSDimitry Andric 
10059dba64beSDimitry Andric   return std::move(backtrace.get());
10069dba64beSDimitry Andric }
10079dba64beSDimitry Andric 
10089dba64beSDimitry Andric char PythonException::ID = 0;
10099dba64beSDimitry Andric 
10109dba64beSDimitry Andric llvm::Expected<File::OpenOptions>
10119dba64beSDimitry Andric GetOptionsForPyObject(const PythonObject &obj) {
10129dba64beSDimitry Andric   auto options = File::OpenOptions(0);
10139dba64beSDimitry Andric   auto readable = As<bool>(obj.CallMethod("readable"));
10149dba64beSDimitry Andric   if (!readable)
10159dba64beSDimitry Andric     return readable.takeError();
10169dba64beSDimitry Andric   auto writable = As<bool>(obj.CallMethod("writable"));
10179dba64beSDimitry Andric   if (!writable)
10189dba64beSDimitry Andric     return writable.takeError();
1019349cc55cSDimitry Andric   if (readable.get() && writable.get())
1020349cc55cSDimitry Andric     options |= File::eOpenOptionReadWrite;
1021349cc55cSDimitry Andric   else if (writable.get())
1022349cc55cSDimitry Andric     options |= File::eOpenOptionWriteOnly;
1023349cc55cSDimitry Andric   else if (readable.get())
1024349cc55cSDimitry Andric     options |= File::eOpenOptionReadOnly;
10259dba64beSDimitry Andric   return options;
10269dba64beSDimitry Andric }
10279dba64beSDimitry Andric 
10289dba64beSDimitry Andric // Base class template for python files.   All it knows how to do
10299dba64beSDimitry Andric // is hold a reference to the python object and close or flush it
10309dba64beSDimitry Andric // when the File is closed.
10319dba64beSDimitry Andric namespace {
10329dba64beSDimitry Andric template <typename Base> class OwnedPythonFile : public Base {
10339dba64beSDimitry Andric public:
10349dba64beSDimitry Andric   template <typename... Args>
10359dba64beSDimitry Andric   OwnedPythonFile(const PythonFile &file, bool borrowed, Args... args)
10369dba64beSDimitry Andric       : Base(args...), m_py_obj(file), m_borrowed(borrowed) {
10379dba64beSDimitry Andric     assert(m_py_obj);
10389dba64beSDimitry Andric   }
10399dba64beSDimitry Andric 
10409dba64beSDimitry Andric   ~OwnedPythonFile() override {
10419dba64beSDimitry Andric     assert(m_py_obj);
10429dba64beSDimitry Andric     GIL takeGIL;
10439dba64beSDimitry Andric     Close();
10449dba64beSDimitry Andric     // we need to ensure the python object is released while we still
10459dba64beSDimitry Andric     // hold the GIL
10469dba64beSDimitry Andric     m_py_obj.Reset();
10479dba64beSDimitry Andric   }
10489dba64beSDimitry Andric 
10499dba64beSDimitry Andric   bool IsPythonSideValid() const {
10509dba64beSDimitry Andric     GIL takeGIL;
10519dba64beSDimitry Andric     auto closed = As<bool>(m_py_obj.GetAttribute("closed"));
10529dba64beSDimitry Andric     if (!closed) {
10539dba64beSDimitry Andric       llvm::consumeError(closed.takeError());
10549dba64beSDimitry Andric       return false;
10559dba64beSDimitry Andric     }
10569dba64beSDimitry Andric     return !closed.get();
10579dba64beSDimitry Andric   }
10589dba64beSDimitry Andric 
10599dba64beSDimitry Andric   bool IsValid() const override {
10609dba64beSDimitry Andric     return IsPythonSideValid() && Base::IsValid();
10619dba64beSDimitry Andric   }
10629dba64beSDimitry Andric 
10639dba64beSDimitry Andric   Status Close() override {
10649dba64beSDimitry Andric     assert(m_py_obj);
10659dba64beSDimitry Andric     Status py_error, base_error;
10669dba64beSDimitry Andric     GIL takeGIL;
10679dba64beSDimitry Andric     if (!m_borrowed) {
10689dba64beSDimitry Andric       auto r = m_py_obj.CallMethod("close");
10699dba64beSDimitry Andric       if (!r)
10709dba64beSDimitry Andric         py_error = Status(r.takeError());
10719dba64beSDimitry Andric     }
10729dba64beSDimitry Andric     base_error = Base::Close();
10739dba64beSDimitry Andric     if (py_error.Fail())
10749dba64beSDimitry Andric       return py_error;
10759dba64beSDimitry Andric     return base_error;
10769dba64beSDimitry Andric   };
10779dba64beSDimitry Andric 
10789dba64beSDimitry Andric   PyObject *GetPythonObject() const {
10799dba64beSDimitry Andric     assert(m_py_obj.IsValid());
10809dba64beSDimitry Andric     return m_py_obj.get();
10819dba64beSDimitry Andric   }
10829dba64beSDimitry Andric 
10839dba64beSDimitry Andric   static bool classof(const File *file) = delete;
10849dba64beSDimitry Andric 
10859dba64beSDimitry Andric protected:
10869dba64beSDimitry Andric   PythonFile m_py_obj;
10879dba64beSDimitry Andric   bool m_borrowed;
10889dba64beSDimitry Andric };
10899dba64beSDimitry Andric } // namespace
10909dba64beSDimitry Andric 
10919dba64beSDimitry Andric // A SimplePythonFile is a OwnedPythonFile that just does all I/O as
10929dba64beSDimitry Andric // a NativeFile
10939dba64beSDimitry Andric namespace {
10949dba64beSDimitry Andric class SimplePythonFile : public OwnedPythonFile<NativeFile> {
10959dba64beSDimitry Andric public:
10969dba64beSDimitry Andric   SimplePythonFile(const PythonFile &file, bool borrowed, int fd,
10979dba64beSDimitry Andric                    File::OpenOptions options)
10989dba64beSDimitry Andric       : OwnedPythonFile(file, borrowed, fd, options, false) {}
10999dba64beSDimitry Andric 
11009dba64beSDimitry Andric   static char ID;
11019dba64beSDimitry Andric   bool isA(const void *classID) const override {
11029dba64beSDimitry Andric     return classID == &ID || NativeFile::isA(classID);
11039dba64beSDimitry Andric   }
11049dba64beSDimitry Andric   static bool classof(const File *file) { return file->isA(&ID); }
11059dba64beSDimitry Andric };
11069dba64beSDimitry Andric char SimplePythonFile::ID = 0;
11079dba64beSDimitry Andric } // namespace
11089dba64beSDimitry Andric 
11099dba64beSDimitry Andric namespace {
11109dba64beSDimitry Andric class PythonBuffer {
11119dba64beSDimitry Andric public:
11129dba64beSDimitry Andric   PythonBuffer &operator=(const PythonBuffer &) = delete;
11139dba64beSDimitry Andric   PythonBuffer(const PythonBuffer &) = delete;
11149dba64beSDimitry Andric 
11159dba64beSDimitry Andric   static Expected<PythonBuffer> Create(PythonObject &obj,
11169dba64beSDimitry Andric                                        int flags = PyBUF_SIMPLE) {
11179dba64beSDimitry Andric     Py_buffer py_buffer = {};
11189dba64beSDimitry Andric     PyObject_GetBuffer(obj.get(), &py_buffer, flags);
11199dba64beSDimitry Andric     if (!py_buffer.obj)
11209dba64beSDimitry Andric       return llvm::make_error<PythonException>();
11219dba64beSDimitry Andric     return PythonBuffer(py_buffer);
11229dba64beSDimitry Andric   }
11239dba64beSDimitry Andric 
11249dba64beSDimitry Andric   PythonBuffer(PythonBuffer &&other) {
11259dba64beSDimitry Andric     m_buffer = other.m_buffer;
11269dba64beSDimitry Andric     other.m_buffer.obj = nullptr;
11279dba64beSDimitry Andric   }
11289dba64beSDimitry Andric 
11299dba64beSDimitry Andric   ~PythonBuffer() {
11309dba64beSDimitry Andric     if (m_buffer.obj)
11319dba64beSDimitry Andric       PyBuffer_Release(&m_buffer);
11329dba64beSDimitry Andric   }
11339dba64beSDimitry Andric 
11349dba64beSDimitry Andric   Py_buffer &get() { return m_buffer; }
11359dba64beSDimitry Andric 
11369dba64beSDimitry Andric private:
11379dba64beSDimitry Andric   // takes ownership of the buffer.
11389dba64beSDimitry Andric   PythonBuffer(const Py_buffer &py_buffer) : m_buffer(py_buffer) {}
11399dba64beSDimitry Andric   Py_buffer m_buffer;
11409dba64beSDimitry Andric };
11419dba64beSDimitry Andric } // namespace
11429dba64beSDimitry Andric 
11439dba64beSDimitry Andric // Shared methods between TextPythonFile and BinaryPythonFile
11449dba64beSDimitry Andric namespace {
11459dba64beSDimitry Andric class PythonIOFile : public OwnedPythonFile<File> {
11469dba64beSDimitry Andric public:
11479dba64beSDimitry Andric   PythonIOFile(const PythonFile &file, bool borrowed)
11489dba64beSDimitry Andric       : OwnedPythonFile(file, borrowed) {}
11499dba64beSDimitry Andric 
11509dba64beSDimitry Andric   ~PythonIOFile() override { Close(); }
11519dba64beSDimitry Andric 
11529dba64beSDimitry Andric   bool IsValid() const override { return IsPythonSideValid(); }
11539dba64beSDimitry Andric 
11549dba64beSDimitry Andric   Status Close() override {
11559dba64beSDimitry Andric     assert(m_py_obj);
11569dba64beSDimitry Andric     GIL takeGIL;
11579dba64beSDimitry Andric     if (m_borrowed)
11589dba64beSDimitry Andric       return Flush();
11599dba64beSDimitry Andric     auto r = m_py_obj.CallMethod("close");
11609dba64beSDimitry Andric     if (!r)
11619dba64beSDimitry Andric       return Status(r.takeError());
11629dba64beSDimitry Andric     return Status();
11639dba64beSDimitry Andric   }
11649dba64beSDimitry Andric 
11659dba64beSDimitry Andric   Status Flush() override {
11669dba64beSDimitry Andric     GIL takeGIL;
11679dba64beSDimitry Andric     auto r = m_py_obj.CallMethod("flush");
11689dba64beSDimitry Andric     if (!r)
11699dba64beSDimitry Andric       return Status(r.takeError());
11709dba64beSDimitry Andric     return Status();
11719dba64beSDimitry Andric   }
11729dba64beSDimitry Andric 
11739dba64beSDimitry Andric   Expected<File::OpenOptions> GetOptions() const override {
11749dba64beSDimitry Andric     GIL takeGIL;
11759dba64beSDimitry Andric     return GetOptionsForPyObject(m_py_obj);
11769dba64beSDimitry Andric   }
11779dba64beSDimitry Andric 
11789dba64beSDimitry Andric   static char ID;
11799dba64beSDimitry Andric   bool isA(const void *classID) const override {
11809dba64beSDimitry Andric     return classID == &ID || File::isA(classID);
11819dba64beSDimitry Andric   }
11829dba64beSDimitry Andric   static bool classof(const File *file) { return file->isA(&ID); }
11839dba64beSDimitry Andric };
11849dba64beSDimitry Andric char PythonIOFile::ID = 0;
11859dba64beSDimitry Andric } // namespace
11869dba64beSDimitry Andric 
11879dba64beSDimitry Andric namespace {
11889dba64beSDimitry Andric class BinaryPythonFile : public PythonIOFile {
11899dba64beSDimitry Andric protected:
11909dba64beSDimitry Andric   int m_descriptor;
11919dba64beSDimitry Andric 
11929dba64beSDimitry Andric public:
11939dba64beSDimitry Andric   BinaryPythonFile(int fd, const PythonFile &file, bool borrowed)
11949dba64beSDimitry Andric       : PythonIOFile(file, borrowed),
11959dba64beSDimitry Andric         m_descriptor(File::DescriptorIsValid(fd) ? fd
11969dba64beSDimitry Andric                                                  : File::kInvalidDescriptor) {}
11979dba64beSDimitry Andric 
11989dba64beSDimitry Andric   int GetDescriptor() const override { return m_descriptor; }
11999dba64beSDimitry Andric 
12009dba64beSDimitry Andric   Status Write(const void *buf, size_t &num_bytes) override {
12019dba64beSDimitry Andric     GIL takeGIL;
12029dba64beSDimitry Andric     PyObject *pybuffer_p = PyMemoryView_FromMemory(
12039dba64beSDimitry Andric         const_cast<char *>((const char *)buf), num_bytes, PyBUF_READ);
12049dba64beSDimitry Andric     if (!pybuffer_p)
12059dba64beSDimitry Andric       return Status(llvm::make_error<PythonException>());
12069dba64beSDimitry Andric     auto pybuffer = Take<PythonObject>(pybuffer_p);
12079dba64beSDimitry Andric     num_bytes = 0;
12089dba64beSDimitry Andric     auto bytes_written = As<long long>(m_py_obj.CallMethod("write", pybuffer));
12099dba64beSDimitry Andric     if (!bytes_written)
12109dba64beSDimitry Andric       return Status(bytes_written.takeError());
12119dba64beSDimitry Andric     if (bytes_written.get() < 0)
12129dba64beSDimitry Andric       return Status(".write() method returned a negative number!");
12139dba64beSDimitry Andric     static_assert(sizeof(long long) >= sizeof(size_t), "overflow");
12149dba64beSDimitry Andric     num_bytes = bytes_written.get();
12159dba64beSDimitry Andric     return Status();
12169dba64beSDimitry Andric   }
12179dba64beSDimitry Andric 
12189dba64beSDimitry Andric   Status Read(void *buf, size_t &num_bytes) override {
12199dba64beSDimitry Andric     GIL takeGIL;
12209dba64beSDimitry Andric     static_assert(sizeof(long long) >= sizeof(size_t), "overflow");
12219dba64beSDimitry Andric     auto pybuffer_obj =
12229dba64beSDimitry Andric         m_py_obj.CallMethod("read", (unsigned long long)num_bytes);
12239dba64beSDimitry Andric     if (!pybuffer_obj)
12249dba64beSDimitry Andric       return Status(pybuffer_obj.takeError());
12259dba64beSDimitry Andric     num_bytes = 0;
12269dba64beSDimitry Andric     if (pybuffer_obj.get().IsNone()) {
12279dba64beSDimitry Andric       // EOF
12289dba64beSDimitry Andric       num_bytes = 0;
12299dba64beSDimitry Andric       return Status();
12309dba64beSDimitry Andric     }
12319dba64beSDimitry Andric     auto pybuffer = PythonBuffer::Create(pybuffer_obj.get());
12329dba64beSDimitry Andric     if (!pybuffer)
12339dba64beSDimitry Andric       return Status(pybuffer.takeError());
12349dba64beSDimitry Andric     memcpy(buf, pybuffer.get().get().buf, pybuffer.get().get().len);
12359dba64beSDimitry Andric     num_bytes = pybuffer.get().get().len;
12369dba64beSDimitry Andric     return Status();
12379dba64beSDimitry Andric   }
12389dba64beSDimitry Andric };
12399dba64beSDimitry Andric } // namespace
12409dba64beSDimitry Andric 
12419dba64beSDimitry Andric namespace {
12429dba64beSDimitry Andric class TextPythonFile : public PythonIOFile {
12439dba64beSDimitry Andric protected:
12449dba64beSDimitry Andric   int m_descriptor;
12459dba64beSDimitry Andric 
12469dba64beSDimitry Andric public:
12479dba64beSDimitry Andric   TextPythonFile(int fd, const PythonFile &file, bool borrowed)
12489dba64beSDimitry Andric       : PythonIOFile(file, borrowed),
12499dba64beSDimitry Andric         m_descriptor(File::DescriptorIsValid(fd) ? fd
12509dba64beSDimitry Andric                                                  : File::kInvalidDescriptor) {}
12519dba64beSDimitry Andric 
12529dba64beSDimitry Andric   int GetDescriptor() const override { return m_descriptor; }
12539dba64beSDimitry Andric 
12549dba64beSDimitry Andric   Status Write(const void *buf, size_t &num_bytes) override {
12559dba64beSDimitry Andric     GIL takeGIL;
12569dba64beSDimitry Andric     auto pystring =
12579dba64beSDimitry Andric         PythonString::FromUTF8(llvm::StringRef((const char *)buf, num_bytes));
12589dba64beSDimitry Andric     if (!pystring)
12599dba64beSDimitry Andric       return Status(pystring.takeError());
12609dba64beSDimitry Andric     num_bytes = 0;
12619dba64beSDimitry Andric     auto bytes_written =
12629dba64beSDimitry Andric         As<long long>(m_py_obj.CallMethod("write", pystring.get()));
12639dba64beSDimitry Andric     if (!bytes_written)
12649dba64beSDimitry Andric       return Status(bytes_written.takeError());
12659dba64beSDimitry Andric     if (bytes_written.get() < 0)
12669dba64beSDimitry Andric       return Status(".write() method returned a negative number!");
12679dba64beSDimitry Andric     static_assert(sizeof(long long) >= sizeof(size_t), "overflow");
12689dba64beSDimitry Andric     num_bytes = bytes_written.get();
12699dba64beSDimitry Andric     return Status();
12709dba64beSDimitry Andric   }
12719dba64beSDimitry Andric 
12729dba64beSDimitry Andric   Status Read(void *buf, size_t &num_bytes) override {
12739dba64beSDimitry Andric     GIL takeGIL;
12749dba64beSDimitry Andric     size_t num_chars = num_bytes / 6;
12759dba64beSDimitry Andric     size_t orig_num_bytes = num_bytes;
12769dba64beSDimitry Andric     num_bytes = 0;
12779dba64beSDimitry Andric     if (orig_num_bytes < 6) {
12789dba64beSDimitry Andric       return Status("can't read less than 6 bytes from a utf8 text stream");
12799dba64beSDimitry Andric     }
12809dba64beSDimitry Andric     auto pystring = As<PythonString>(
12819dba64beSDimitry Andric         m_py_obj.CallMethod("read", (unsigned long long)num_chars));
12829dba64beSDimitry Andric     if (!pystring)
12839dba64beSDimitry Andric       return Status(pystring.takeError());
12849dba64beSDimitry Andric     if (pystring.get().IsNone()) {
12859dba64beSDimitry Andric       // EOF
12869dba64beSDimitry Andric       return Status();
12879dba64beSDimitry Andric     }
12889dba64beSDimitry Andric     auto stringref = pystring.get().AsUTF8();
12899dba64beSDimitry Andric     if (!stringref)
12909dba64beSDimitry Andric       return Status(stringref.takeError());
12919dba64beSDimitry Andric     num_bytes = stringref.get().size();
12929dba64beSDimitry Andric     memcpy(buf, stringref.get().begin(), num_bytes);
12939dba64beSDimitry Andric     return Status();
12949dba64beSDimitry Andric   }
12959dba64beSDimitry Andric };
12969dba64beSDimitry Andric } // namespace
12979dba64beSDimitry Andric 
12989dba64beSDimitry Andric llvm::Expected<FileSP> PythonFile::ConvertToFile(bool borrowed) {
12999dba64beSDimitry Andric   if (!IsValid())
13009dba64beSDimitry Andric     return llvm::createStringError(llvm::inconvertibleErrorCode(),
13019dba64beSDimitry Andric                                    "invalid PythonFile");
13029dba64beSDimitry Andric 
13039dba64beSDimitry Andric   int fd = PyObject_AsFileDescriptor(m_py_obj);
13049dba64beSDimitry Andric   if (fd < 0) {
13059dba64beSDimitry Andric     PyErr_Clear();
13069dba64beSDimitry Andric     return ConvertToFileForcingUseOfScriptingIOMethods(borrowed);
13079dba64beSDimitry Andric   }
13089dba64beSDimitry Andric   auto options = GetOptionsForPyObject(*this);
13099dba64beSDimitry Andric   if (!options)
13109dba64beSDimitry Andric     return options.takeError();
13119dba64beSDimitry Andric 
1312349cc55cSDimitry Andric   File::OpenOptions rw =
1313349cc55cSDimitry Andric       options.get() & (File::eOpenOptionReadOnly | File::eOpenOptionWriteOnly |
1314349cc55cSDimitry Andric                        File::eOpenOptionReadWrite);
1315349cc55cSDimitry Andric   if (rw == File::eOpenOptionWriteOnly || rw == File::eOpenOptionReadWrite) {
13169dba64beSDimitry Andric     // LLDB and python will not share I/O buffers.  We should probably
13179dba64beSDimitry Andric     // flush the python buffers now.
13189dba64beSDimitry Andric     auto r = CallMethod("flush");
13199dba64beSDimitry Andric     if (!r)
13209dba64beSDimitry Andric       return r.takeError();
1321480093f4SDimitry Andric   }
13229dba64beSDimitry Andric 
13239dba64beSDimitry Andric   FileSP file_sp;
13249dba64beSDimitry Andric   if (borrowed) {
13259dba64beSDimitry Andric     // In this case we we don't need to retain the python
13269dba64beSDimitry Andric     // object at all.
13279dba64beSDimitry Andric     file_sp = std::make_shared<NativeFile>(fd, options.get(), false);
13289dba64beSDimitry Andric   } else {
13299dba64beSDimitry Andric     file_sp = std::static_pointer_cast<File>(
13309dba64beSDimitry Andric         std::make_shared<SimplePythonFile>(*this, borrowed, fd, options.get()));
13319dba64beSDimitry Andric   }
13329dba64beSDimitry Andric   if (!file_sp->IsValid())
13339dba64beSDimitry Andric     return llvm::createStringError(llvm::inconvertibleErrorCode(),
13349dba64beSDimitry Andric                                    "invalid File");
13359dba64beSDimitry Andric 
13369dba64beSDimitry Andric   return file_sp;
13379dba64beSDimitry Andric }
13389dba64beSDimitry Andric 
13399dba64beSDimitry Andric llvm::Expected<FileSP>
13409dba64beSDimitry Andric PythonFile::ConvertToFileForcingUseOfScriptingIOMethods(bool borrowed) {
13419dba64beSDimitry Andric 
13429dba64beSDimitry Andric   assert(!PyErr_Occurred());
13439dba64beSDimitry Andric 
13449dba64beSDimitry Andric   if (!IsValid())
13459dba64beSDimitry Andric     return llvm::createStringError(llvm::inconvertibleErrorCode(),
13469dba64beSDimitry Andric                                    "invalid PythonFile");
13479dba64beSDimitry Andric 
13489dba64beSDimitry Andric   int fd = PyObject_AsFileDescriptor(m_py_obj);
13499dba64beSDimitry Andric   if (fd < 0) {
13509dba64beSDimitry Andric     PyErr_Clear();
13519dba64beSDimitry Andric     fd = File::kInvalidDescriptor;
13529dba64beSDimitry Andric   }
13539dba64beSDimitry Andric 
13549dba64beSDimitry Andric   auto io_module = PythonModule::Import("io");
13559dba64beSDimitry Andric   if (!io_module)
13569dba64beSDimitry Andric     return io_module.takeError();
13579dba64beSDimitry Andric   auto textIOBase = io_module.get().Get("TextIOBase");
13589dba64beSDimitry Andric   if (!textIOBase)
13599dba64beSDimitry Andric     return textIOBase.takeError();
13609dba64beSDimitry Andric   auto rawIOBase = io_module.get().Get("RawIOBase");
13619dba64beSDimitry Andric   if (!rawIOBase)
13629dba64beSDimitry Andric     return rawIOBase.takeError();
13639dba64beSDimitry Andric   auto bufferedIOBase = io_module.get().Get("BufferedIOBase");
13649dba64beSDimitry Andric   if (!bufferedIOBase)
13659dba64beSDimitry Andric     return bufferedIOBase.takeError();
13669dba64beSDimitry Andric 
13679dba64beSDimitry Andric   FileSP file_sp;
13689dba64beSDimitry Andric 
13699dba64beSDimitry Andric   auto isTextIO = IsInstance(textIOBase.get());
13709dba64beSDimitry Andric   if (!isTextIO)
13719dba64beSDimitry Andric     return isTextIO.takeError();
13729dba64beSDimitry Andric   if (isTextIO.get())
13739dba64beSDimitry Andric     file_sp = std::static_pointer_cast<File>(
13749dba64beSDimitry Andric         std::make_shared<TextPythonFile>(fd, *this, borrowed));
13759dba64beSDimitry Andric 
13769dba64beSDimitry Andric   auto isRawIO = IsInstance(rawIOBase.get());
13779dba64beSDimitry Andric   if (!isRawIO)
13789dba64beSDimitry Andric     return isRawIO.takeError();
13799dba64beSDimitry Andric   auto isBufferedIO = IsInstance(bufferedIOBase.get());
13809dba64beSDimitry Andric   if (!isBufferedIO)
13819dba64beSDimitry Andric     return isBufferedIO.takeError();
13829dba64beSDimitry Andric 
13839dba64beSDimitry Andric   if (isRawIO.get() || isBufferedIO.get()) {
13849dba64beSDimitry Andric     file_sp = std::static_pointer_cast<File>(
13859dba64beSDimitry Andric         std::make_shared<BinaryPythonFile>(fd, *this, borrowed));
13869dba64beSDimitry Andric   }
13879dba64beSDimitry Andric 
13889dba64beSDimitry Andric   if (!file_sp)
13899dba64beSDimitry Andric     return llvm::createStringError(llvm::inconvertibleErrorCode(),
13909dba64beSDimitry Andric                                    "python file is neither text nor binary");
13919dba64beSDimitry Andric 
13929dba64beSDimitry Andric   if (!file_sp->IsValid())
13939dba64beSDimitry Andric     return llvm::createStringError(llvm::inconvertibleErrorCode(),
13949dba64beSDimitry Andric                                    "invalid File");
13959dba64beSDimitry Andric 
13969dba64beSDimitry Andric   return file_sp;
13979dba64beSDimitry Andric }
13989dba64beSDimitry Andric 
13999dba64beSDimitry Andric Expected<PythonFile> PythonFile::FromFile(File &file, const char *mode) {
14009dba64beSDimitry Andric   if (!file.IsValid())
14019dba64beSDimitry Andric     return llvm::createStringError(llvm::inconvertibleErrorCode(),
14029dba64beSDimitry Andric                                    "invalid file");
14039dba64beSDimitry Andric 
14049dba64beSDimitry Andric   if (auto *simple = llvm::dyn_cast<SimplePythonFile>(&file))
14059dba64beSDimitry Andric     return Retain<PythonFile>(simple->GetPythonObject());
14069dba64beSDimitry Andric   if (auto *pythonio = llvm::dyn_cast<PythonIOFile>(&file))
14079dba64beSDimitry Andric     return Retain<PythonFile>(pythonio->GetPythonObject());
14089dba64beSDimitry Andric 
14099dba64beSDimitry Andric   if (!mode) {
14109dba64beSDimitry Andric     auto m = file.GetOpenMode();
14119dba64beSDimitry Andric     if (!m)
14129dba64beSDimitry Andric       return m.takeError();
14139dba64beSDimitry Andric     mode = m.get();
14149dba64beSDimitry Andric   }
14159dba64beSDimitry Andric 
14169dba64beSDimitry Andric   PyObject *file_obj;
14179dba64beSDimitry Andric   file_obj = PyFile_FromFd(file.GetDescriptor(), nullptr, mode, -1, nullptr,
1418480093f4SDimitry Andric                            "ignore", nullptr, /*closefd=*/0);
14199dba64beSDimitry Andric 
14209dba64beSDimitry Andric   if (!file_obj)
14219dba64beSDimitry Andric     return exception();
14229dba64beSDimitry Andric 
14239dba64beSDimitry Andric   return Take<PythonFile>(file_obj);
14240b57cec5SDimitry Andric }
14250b57cec5SDimitry Andric 
14269dba64beSDimitry Andric Error PythonScript::Init() {
14279dba64beSDimitry Andric   if (function.IsValid())
14289dba64beSDimitry Andric     return Error::success();
14290b57cec5SDimitry Andric 
14309dba64beSDimitry Andric   PythonDictionary globals(PyInitialValue::Empty);
14319dba64beSDimitry Andric   auto builtins = PythonModule::BuiltinsModule();
14329dba64beSDimitry Andric   if (Error error = globals.SetItem("__builtins__", builtins))
14339dba64beSDimitry Andric     return error;
14349dba64beSDimitry Andric   PyObject *o =
14359dba64beSDimitry Andric       PyRun_String(script, Py_file_input, globals.get(), globals.get());
14369dba64beSDimitry Andric   if (!o)
14379dba64beSDimitry Andric     return exception();
14389dba64beSDimitry Andric   Take<PythonObject>(o);
14399dba64beSDimitry Andric   auto f = As<PythonCallable>(globals.GetItem("main"));
14409dba64beSDimitry Andric   if (!f)
14419dba64beSDimitry Andric     return f.takeError();
14429dba64beSDimitry Andric   function = std::move(f.get());
14439dba64beSDimitry Andric 
14449dba64beSDimitry Andric   return Error::success();
14450b57cec5SDimitry Andric }
14460b57cec5SDimitry Andric 
14479dba64beSDimitry Andric llvm::Expected<PythonObject>
14489dba64beSDimitry Andric python::runStringOneLine(const llvm::Twine &string,
14499dba64beSDimitry Andric                          const PythonDictionary &globals,
14509dba64beSDimitry Andric                          const PythonDictionary &locals) {
14519dba64beSDimitry Andric   if (!globals.IsValid() || !locals.IsValid())
14529dba64beSDimitry Andric     return nullDeref();
14530b57cec5SDimitry Andric 
14549dba64beSDimitry Andric   PyObject *code =
14559dba64beSDimitry Andric       Py_CompileString(NullTerminated(string), "<string>", Py_eval_input);
14569dba64beSDimitry Andric   if (!code) {
14579dba64beSDimitry Andric     PyErr_Clear();
14589dba64beSDimitry Andric     code =
14599dba64beSDimitry Andric         Py_CompileString(NullTerminated(string), "<string>", Py_single_input);
14609dba64beSDimitry Andric   }
14619dba64beSDimitry Andric   if (!code)
14629dba64beSDimitry Andric     return exception();
14639dba64beSDimitry Andric   auto code_ref = Take<PythonObject>(code);
14649dba64beSDimitry Andric 
14659dba64beSDimitry Andric   PyObject *result = PyEval_EvalCode(code, globals.get(), locals.get());
14669dba64beSDimitry Andric 
14679dba64beSDimitry Andric   if (!result)
14689dba64beSDimitry Andric     return exception();
14699dba64beSDimitry Andric 
14709dba64beSDimitry Andric   return Take<PythonObject>(result);
14719dba64beSDimitry Andric }
14729dba64beSDimitry Andric 
14739dba64beSDimitry Andric llvm::Expected<PythonObject>
14749dba64beSDimitry Andric python::runStringMultiLine(const llvm::Twine &string,
14759dba64beSDimitry Andric                            const PythonDictionary &globals,
14769dba64beSDimitry Andric                            const PythonDictionary &locals) {
14779dba64beSDimitry Andric   if (!globals.IsValid() || !locals.IsValid())
14789dba64beSDimitry Andric     return nullDeref();
14799dba64beSDimitry Andric   PyObject *result = PyRun_String(NullTerminated(string), Py_file_input,
14809dba64beSDimitry Andric                                   globals.get(), locals.get());
14819dba64beSDimitry Andric   if (!result)
14829dba64beSDimitry Andric     return exception();
14839dba64beSDimitry Andric   return Take<PythonObject>(result);
14840b57cec5SDimitry Andric }
14850b57cec5SDimitry Andric 
14860b57cec5SDimitry Andric #endif
1487