xref: /freebsd-src/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.cpp (revision 9dba64be9536c28e4800e06512b7f29b43ade345)
10b57cec5SDimitry Andric //===-- PythonDataObjects.cpp -----------------------------------*- C++ -*-===//
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 
90b57cec5SDimitry Andric #ifdef LLDB_DISABLE_PYTHON
100b57cec5SDimitry Andric 
110b57cec5SDimitry Andric // Python is disabled in this build
120b57cec5SDimitry Andric 
130b57cec5SDimitry Andric #else
140b57cec5SDimitry Andric 
150b57cec5SDimitry Andric #include "PythonDataObjects.h"
160b57cec5SDimitry Andric #include "ScriptInterpreterPython.h"
170b57cec5SDimitry Andric 
180b57cec5SDimitry Andric #include "lldb/Host/File.h"
190b57cec5SDimitry Andric #include "lldb/Host/FileSystem.h"
200b57cec5SDimitry Andric #include "lldb/Interpreter/ScriptInterpreter.h"
21*9dba64beSDimitry Andric #include "lldb/Utility/Log.h"
220b57cec5SDimitry Andric #include "lldb/Utility/Stream.h"
230b57cec5SDimitry Andric 
240b57cec5SDimitry Andric #include "llvm/ADT/StringSwitch.h"
25*9dba64beSDimitry Andric #include "llvm/Support/Casting.h"
260b57cec5SDimitry Andric #include "llvm/Support/ConvertUTF.h"
270b57cec5SDimitry Andric #include "llvm/Support/Errno.h"
280b57cec5SDimitry Andric 
290b57cec5SDimitry Andric #include <stdio.h>
300b57cec5SDimitry Andric 
310b57cec5SDimitry Andric using namespace lldb_private;
320b57cec5SDimitry Andric using namespace lldb;
33*9dba64beSDimitry Andric using namespace lldb_private::python;
34*9dba64beSDimitry Andric using llvm::cantFail;
35*9dba64beSDimitry Andric using llvm::Error;
36*9dba64beSDimitry Andric using llvm::Expected;
37*9dba64beSDimitry Andric using llvm::Twine;
380b57cec5SDimitry Andric 
39*9dba64beSDimitry Andric template <> Expected<bool> python::As<bool>(Expected<PythonObject> &&obj) {
40*9dba64beSDimitry Andric   if (!obj)
41*9dba64beSDimitry Andric     return obj.takeError();
42*9dba64beSDimitry Andric   return obj.get().IsTrue();
43*9dba64beSDimitry Andric }
44*9dba64beSDimitry Andric 
45*9dba64beSDimitry Andric template <>
46*9dba64beSDimitry Andric Expected<long long> python::As<long long>(Expected<PythonObject> &&obj) {
47*9dba64beSDimitry Andric   if (!obj)
48*9dba64beSDimitry Andric     return obj.takeError();
49*9dba64beSDimitry Andric   return obj.get().AsLongLong();
50*9dba64beSDimitry Andric }
51*9dba64beSDimitry Andric 
52*9dba64beSDimitry Andric template <>
53*9dba64beSDimitry Andric Expected<std::string> python::As<std::string>(Expected<PythonObject> &&obj) {
54*9dba64beSDimitry Andric   if (!obj)
55*9dba64beSDimitry Andric     return obj.takeError();
56*9dba64beSDimitry Andric   PyObject *str_obj = PyObject_Str(obj.get().get());
57*9dba64beSDimitry Andric   if (!obj)
58*9dba64beSDimitry Andric     return llvm::make_error<PythonException>();
59*9dba64beSDimitry Andric   auto str = Take<PythonString>(str_obj);
60*9dba64beSDimitry Andric   auto utf8 = str.AsUTF8();
61*9dba64beSDimitry Andric   if (!utf8)
62*9dba64beSDimitry Andric     return utf8.takeError();
63*9dba64beSDimitry Andric   return utf8.get();
64*9dba64beSDimitry Andric }
65*9dba64beSDimitry Andric 
66*9dba64beSDimitry Andric void StructuredPythonObject::Serialize(llvm::json::OStream &s) const {
67*9dba64beSDimitry Andric   s.value(llvm::formatv("Python Obj: {0:X}", GetValue()).str());
680b57cec5SDimitry Andric }
690b57cec5SDimitry Andric 
700b57cec5SDimitry Andric // PythonObject
710b57cec5SDimitry Andric 
720b57cec5SDimitry Andric void PythonObject::Dump(Stream &strm) const {
730b57cec5SDimitry Andric   if (m_py_obj) {
740b57cec5SDimitry Andric     FILE *file = llvm::sys::RetryAfterSignal(nullptr, ::tmpfile);
750b57cec5SDimitry Andric     if (file) {
760b57cec5SDimitry Andric       ::PyObject_Print(m_py_obj, file, 0);
770b57cec5SDimitry Andric       const long length = ftell(file);
780b57cec5SDimitry Andric       if (length) {
790b57cec5SDimitry Andric         ::rewind(file);
800b57cec5SDimitry Andric         std::vector<char> file_contents(length, '\0');
810b57cec5SDimitry Andric         const size_t length_read =
820b57cec5SDimitry Andric             ::fread(file_contents.data(), 1, file_contents.size(), file);
830b57cec5SDimitry Andric         if (length_read > 0)
840b57cec5SDimitry Andric           strm.Write(file_contents.data(), length_read);
850b57cec5SDimitry Andric       }
860b57cec5SDimitry Andric       ::fclose(file);
870b57cec5SDimitry Andric     }
880b57cec5SDimitry Andric   } else
890b57cec5SDimitry Andric     strm.PutCString("NULL");
900b57cec5SDimitry Andric }
910b57cec5SDimitry Andric 
920b57cec5SDimitry Andric PyObjectType PythonObject::GetObjectType() const {
930b57cec5SDimitry Andric   if (!IsAllocated())
940b57cec5SDimitry Andric     return PyObjectType::None;
950b57cec5SDimitry Andric 
960b57cec5SDimitry Andric   if (PythonModule::Check(m_py_obj))
970b57cec5SDimitry Andric     return PyObjectType::Module;
980b57cec5SDimitry Andric   if (PythonList::Check(m_py_obj))
990b57cec5SDimitry Andric     return PyObjectType::List;
1000b57cec5SDimitry Andric   if (PythonTuple::Check(m_py_obj))
1010b57cec5SDimitry Andric     return PyObjectType::Tuple;
1020b57cec5SDimitry Andric   if (PythonDictionary::Check(m_py_obj))
1030b57cec5SDimitry Andric     return PyObjectType::Dictionary;
1040b57cec5SDimitry Andric   if (PythonString::Check(m_py_obj))
1050b57cec5SDimitry Andric     return PyObjectType::String;
1060b57cec5SDimitry Andric #if PY_MAJOR_VERSION >= 3
1070b57cec5SDimitry Andric   if (PythonBytes::Check(m_py_obj))
1080b57cec5SDimitry Andric     return PyObjectType::Bytes;
1090b57cec5SDimitry Andric #endif
1100b57cec5SDimitry Andric   if (PythonByteArray::Check(m_py_obj))
1110b57cec5SDimitry Andric     return PyObjectType::ByteArray;
1120b57cec5SDimitry Andric   if (PythonBoolean::Check(m_py_obj))
1130b57cec5SDimitry Andric     return PyObjectType::Boolean;
1140b57cec5SDimitry Andric   if (PythonInteger::Check(m_py_obj))
1150b57cec5SDimitry Andric     return PyObjectType::Integer;
1160b57cec5SDimitry Andric   if (PythonFile::Check(m_py_obj))
1170b57cec5SDimitry Andric     return PyObjectType::File;
1180b57cec5SDimitry Andric   if (PythonCallable::Check(m_py_obj))
1190b57cec5SDimitry Andric     return PyObjectType::Callable;
1200b57cec5SDimitry Andric   return PyObjectType::Unknown;
1210b57cec5SDimitry Andric }
1220b57cec5SDimitry Andric 
1230b57cec5SDimitry Andric PythonString PythonObject::Repr() const {
1240b57cec5SDimitry Andric   if (!m_py_obj)
1250b57cec5SDimitry Andric     return PythonString();
1260b57cec5SDimitry Andric   PyObject *repr = PyObject_Repr(m_py_obj);
1270b57cec5SDimitry Andric   if (!repr)
1280b57cec5SDimitry Andric     return PythonString();
1290b57cec5SDimitry Andric   return PythonString(PyRefType::Owned, repr);
1300b57cec5SDimitry Andric }
1310b57cec5SDimitry Andric 
1320b57cec5SDimitry Andric PythonString PythonObject::Str() const {
1330b57cec5SDimitry Andric   if (!m_py_obj)
1340b57cec5SDimitry Andric     return PythonString();
1350b57cec5SDimitry Andric   PyObject *str = PyObject_Str(m_py_obj);
1360b57cec5SDimitry Andric   if (!str)
1370b57cec5SDimitry Andric     return PythonString();
1380b57cec5SDimitry Andric   return PythonString(PyRefType::Owned, str);
1390b57cec5SDimitry Andric }
1400b57cec5SDimitry Andric 
1410b57cec5SDimitry Andric PythonObject
1420b57cec5SDimitry Andric PythonObject::ResolveNameWithDictionary(llvm::StringRef name,
1430b57cec5SDimitry Andric                                         const PythonDictionary &dict) {
1440b57cec5SDimitry Andric   size_t dot_pos = name.find('.');
1450b57cec5SDimitry Andric   llvm::StringRef piece = name.substr(0, dot_pos);
1460b57cec5SDimitry Andric   PythonObject result = dict.GetItemForKey(PythonString(piece));
1470b57cec5SDimitry Andric   if (dot_pos == llvm::StringRef::npos) {
1480b57cec5SDimitry Andric     // There was no dot, we're done.
1490b57cec5SDimitry Andric     return result;
1500b57cec5SDimitry Andric   }
1510b57cec5SDimitry Andric 
1520b57cec5SDimitry Andric   // There was a dot.  The remaining portion of the name should be looked up in
1530b57cec5SDimitry Andric   // the context of the object that was found in the dictionary.
1540b57cec5SDimitry Andric   return result.ResolveName(name.substr(dot_pos + 1));
1550b57cec5SDimitry Andric }
1560b57cec5SDimitry Andric 
1570b57cec5SDimitry Andric PythonObject PythonObject::ResolveName(llvm::StringRef name) const {
1580b57cec5SDimitry Andric   // Resolve the name in the context of the specified object.  If, for example,
1590b57cec5SDimitry Andric   // `this` refers to a PyModule, then this will look for `name` in this
1600b57cec5SDimitry Andric   // module.  If `this` refers to a PyType, then it will resolve `name` as an
1610b57cec5SDimitry Andric   // attribute of that type.  If `this` refers to an instance of an object,
1620b57cec5SDimitry Andric   // then it will resolve `name` as the value of the specified field.
1630b57cec5SDimitry Andric   //
1640b57cec5SDimitry Andric   // This function handles dotted names so that, for example, if `m_py_obj`
1650b57cec5SDimitry Andric   // refers to the `sys` module, and `name` == "path.append", then it will find
1660b57cec5SDimitry Andric   // the function `sys.path.append`.
1670b57cec5SDimitry Andric 
1680b57cec5SDimitry Andric   size_t dot_pos = name.find('.');
1690b57cec5SDimitry Andric   if (dot_pos == llvm::StringRef::npos) {
1700b57cec5SDimitry Andric     // No dots in the name, we should be able to find the value immediately as
1710b57cec5SDimitry Andric     // an attribute of `m_py_obj`.
1720b57cec5SDimitry Andric     return GetAttributeValue(name);
1730b57cec5SDimitry Andric   }
1740b57cec5SDimitry Andric 
1750b57cec5SDimitry Andric   // Look up the first piece of the name, and resolve the rest as a child of
1760b57cec5SDimitry Andric   // that.
1770b57cec5SDimitry Andric   PythonObject parent = ResolveName(name.substr(0, dot_pos));
1780b57cec5SDimitry Andric   if (!parent.IsAllocated())
1790b57cec5SDimitry Andric     return PythonObject();
1800b57cec5SDimitry Andric 
1810b57cec5SDimitry Andric   // Tail recursion.. should be optimized by the compiler
1820b57cec5SDimitry Andric   return parent.ResolveName(name.substr(dot_pos + 1));
1830b57cec5SDimitry Andric }
1840b57cec5SDimitry Andric 
1850b57cec5SDimitry Andric bool PythonObject::HasAttribute(llvm::StringRef attr) const {
1860b57cec5SDimitry Andric   if (!IsValid())
1870b57cec5SDimitry Andric     return false;
1880b57cec5SDimitry Andric   PythonString py_attr(attr);
1890b57cec5SDimitry Andric   return !!PyObject_HasAttr(m_py_obj, py_attr.get());
1900b57cec5SDimitry Andric }
1910b57cec5SDimitry Andric 
1920b57cec5SDimitry Andric PythonObject PythonObject::GetAttributeValue(llvm::StringRef attr) const {
1930b57cec5SDimitry Andric   if (!IsValid())
1940b57cec5SDimitry Andric     return PythonObject();
1950b57cec5SDimitry Andric 
1960b57cec5SDimitry Andric   PythonString py_attr(attr);
1970b57cec5SDimitry Andric   if (!PyObject_HasAttr(m_py_obj, py_attr.get()))
1980b57cec5SDimitry Andric     return PythonObject();
1990b57cec5SDimitry Andric 
2000b57cec5SDimitry Andric   return PythonObject(PyRefType::Owned,
2010b57cec5SDimitry Andric                       PyObject_GetAttr(m_py_obj, py_attr.get()));
2020b57cec5SDimitry Andric }
2030b57cec5SDimitry Andric 
2040b57cec5SDimitry Andric StructuredData::ObjectSP PythonObject::CreateStructuredObject() const {
2050b57cec5SDimitry Andric   switch (GetObjectType()) {
2060b57cec5SDimitry Andric   case PyObjectType::Dictionary:
2070b57cec5SDimitry Andric     return PythonDictionary(PyRefType::Borrowed, m_py_obj)
2080b57cec5SDimitry Andric         .CreateStructuredDictionary();
2090b57cec5SDimitry Andric   case PyObjectType::Boolean:
2100b57cec5SDimitry Andric     return PythonBoolean(PyRefType::Borrowed, m_py_obj)
2110b57cec5SDimitry Andric         .CreateStructuredBoolean();
2120b57cec5SDimitry Andric   case PyObjectType::Integer:
2130b57cec5SDimitry Andric     return PythonInteger(PyRefType::Borrowed, m_py_obj)
2140b57cec5SDimitry Andric         .CreateStructuredInteger();
2150b57cec5SDimitry Andric   case PyObjectType::List:
2160b57cec5SDimitry Andric     return PythonList(PyRefType::Borrowed, m_py_obj).CreateStructuredArray();
2170b57cec5SDimitry Andric   case PyObjectType::String:
2180b57cec5SDimitry Andric     return PythonString(PyRefType::Borrowed, m_py_obj).CreateStructuredString();
2190b57cec5SDimitry Andric   case PyObjectType::Bytes:
2200b57cec5SDimitry Andric     return PythonBytes(PyRefType::Borrowed, m_py_obj).CreateStructuredString();
2210b57cec5SDimitry Andric   case PyObjectType::ByteArray:
2220b57cec5SDimitry Andric     return PythonByteArray(PyRefType::Borrowed, m_py_obj)
2230b57cec5SDimitry Andric         .CreateStructuredString();
2240b57cec5SDimitry Andric   case PyObjectType::None:
2250b57cec5SDimitry Andric     return StructuredData::ObjectSP();
2260b57cec5SDimitry Andric   default:
2270b57cec5SDimitry Andric     return StructuredData::ObjectSP(new StructuredPythonObject(m_py_obj));
2280b57cec5SDimitry Andric   }
2290b57cec5SDimitry Andric }
2300b57cec5SDimitry Andric 
2310b57cec5SDimitry Andric // PythonString
2320b57cec5SDimitry Andric 
233*9dba64beSDimitry Andric PythonBytes::PythonBytes(llvm::ArrayRef<uint8_t> bytes) { SetBytes(bytes); }
2340b57cec5SDimitry Andric 
235*9dba64beSDimitry Andric PythonBytes::PythonBytes(const uint8_t *bytes, size_t length) {
2360b57cec5SDimitry Andric   SetBytes(llvm::ArrayRef<uint8_t>(bytes, length));
2370b57cec5SDimitry Andric }
2380b57cec5SDimitry Andric 
2390b57cec5SDimitry Andric bool PythonBytes::Check(PyObject *py_obj) {
2400b57cec5SDimitry Andric   if (!py_obj)
2410b57cec5SDimitry Andric     return false;
2420b57cec5SDimitry Andric   return PyBytes_Check(py_obj);
2430b57cec5SDimitry Andric }
2440b57cec5SDimitry Andric 
2450b57cec5SDimitry Andric llvm::ArrayRef<uint8_t> PythonBytes::GetBytes() const {
2460b57cec5SDimitry Andric   if (!IsValid())
2470b57cec5SDimitry Andric     return llvm::ArrayRef<uint8_t>();
2480b57cec5SDimitry Andric 
2490b57cec5SDimitry Andric   Py_ssize_t size;
2500b57cec5SDimitry Andric   char *c;
2510b57cec5SDimitry Andric 
2520b57cec5SDimitry Andric   PyBytes_AsStringAndSize(m_py_obj, &c, &size);
2530b57cec5SDimitry Andric   return llvm::ArrayRef<uint8_t>(reinterpret_cast<uint8_t *>(c), size);
2540b57cec5SDimitry Andric }
2550b57cec5SDimitry Andric 
2560b57cec5SDimitry Andric size_t PythonBytes::GetSize() const {
2570b57cec5SDimitry Andric   if (!IsValid())
2580b57cec5SDimitry Andric     return 0;
2590b57cec5SDimitry Andric   return PyBytes_Size(m_py_obj);
2600b57cec5SDimitry Andric }
2610b57cec5SDimitry Andric 
2620b57cec5SDimitry Andric void PythonBytes::SetBytes(llvm::ArrayRef<uint8_t> bytes) {
2630b57cec5SDimitry Andric   const char *data = reinterpret_cast<const char *>(bytes.data());
264*9dba64beSDimitry Andric   *this = Take<PythonBytes>(PyBytes_FromStringAndSize(data, bytes.size()));
2650b57cec5SDimitry Andric }
2660b57cec5SDimitry Andric 
2670b57cec5SDimitry Andric StructuredData::StringSP PythonBytes::CreateStructuredString() const {
2680b57cec5SDimitry Andric   StructuredData::StringSP result(new StructuredData::String);
2690b57cec5SDimitry Andric   Py_ssize_t size;
2700b57cec5SDimitry Andric   char *c;
2710b57cec5SDimitry Andric   PyBytes_AsStringAndSize(m_py_obj, &c, &size);
2720b57cec5SDimitry Andric   result->SetValue(std::string(c, size));
2730b57cec5SDimitry Andric   return result;
2740b57cec5SDimitry Andric }
2750b57cec5SDimitry Andric 
2760b57cec5SDimitry Andric PythonByteArray::PythonByteArray(llvm::ArrayRef<uint8_t> bytes)
2770b57cec5SDimitry Andric     : PythonByteArray(bytes.data(), bytes.size()) {}
2780b57cec5SDimitry Andric 
2790b57cec5SDimitry Andric PythonByteArray::PythonByteArray(const uint8_t *bytes, size_t length) {
2800b57cec5SDimitry Andric   const char *str = reinterpret_cast<const char *>(bytes);
281*9dba64beSDimitry Andric   *this = Take<PythonByteArray>(PyByteArray_FromStringAndSize(str, length));
2820b57cec5SDimitry Andric }
2830b57cec5SDimitry Andric 
2840b57cec5SDimitry Andric bool PythonByteArray::Check(PyObject *py_obj) {
2850b57cec5SDimitry Andric   if (!py_obj)
2860b57cec5SDimitry Andric     return false;
2870b57cec5SDimitry Andric   return PyByteArray_Check(py_obj);
2880b57cec5SDimitry Andric }
2890b57cec5SDimitry Andric 
2900b57cec5SDimitry Andric llvm::ArrayRef<uint8_t> PythonByteArray::GetBytes() const {
2910b57cec5SDimitry Andric   if (!IsValid())
2920b57cec5SDimitry Andric     return llvm::ArrayRef<uint8_t>();
2930b57cec5SDimitry Andric 
2940b57cec5SDimitry Andric   char *c = PyByteArray_AsString(m_py_obj);
2950b57cec5SDimitry Andric   size_t size = GetSize();
2960b57cec5SDimitry Andric   return llvm::ArrayRef<uint8_t>(reinterpret_cast<uint8_t *>(c), size);
2970b57cec5SDimitry Andric }
2980b57cec5SDimitry Andric 
2990b57cec5SDimitry Andric size_t PythonByteArray::GetSize() const {
3000b57cec5SDimitry Andric   if (!IsValid())
3010b57cec5SDimitry Andric     return 0;
3020b57cec5SDimitry Andric 
3030b57cec5SDimitry Andric   return PyByteArray_Size(m_py_obj);
3040b57cec5SDimitry Andric }
3050b57cec5SDimitry Andric 
3060b57cec5SDimitry Andric StructuredData::StringSP PythonByteArray::CreateStructuredString() const {
3070b57cec5SDimitry Andric   StructuredData::StringSP result(new StructuredData::String);
3080b57cec5SDimitry Andric   llvm::ArrayRef<uint8_t> bytes = GetBytes();
3090b57cec5SDimitry Andric   const char *str = reinterpret_cast<const char *>(bytes.data());
3100b57cec5SDimitry Andric   result->SetValue(std::string(str, bytes.size()));
3110b57cec5SDimitry Andric   return result;
3120b57cec5SDimitry Andric }
3130b57cec5SDimitry Andric 
3140b57cec5SDimitry Andric // PythonString
3150b57cec5SDimitry Andric 
316*9dba64beSDimitry Andric Expected<PythonString> PythonString::FromUTF8(llvm::StringRef string) {
317*9dba64beSDimitry Andric #if PY_MAJOR_VERSION >= 3
318*9dba64beSDimitry Andric   PyObject *str = PyUnicode_FromStringAndSize(string.data(), string.size());
319*9dba64beSDimitry Andric #else
320*9dba64beSDimitry Andric   PyObject *str = PyString_FromStringAndSize(string.data(), string.size());
321*9dba64beSDimitry Andric #endif
322*9dba64beSDimitry Andric   if (!str)
323*9dba64beSDimitry Andric     return llvm::make_error<PythonException>();
324*9dba64beSDimitry Andric   return Take<PythonString>(str);
3250b57cec5SDimitry Andric }
3260b57cec5SDimitry Andric 
327*9dba64beSDimitry Andric PythonString::PythonString(llvm::StringRef string) { SetString(string); }
3280b57cec5SDimitry Andric 
3290b57cec5SDimitry Andric bool PythonString::Check(PyObject *py_obj) {
3300b57cec5SDimitry Andric   if (!py_obj)
3310b57cec5SDimitry Andric     return false;
3320b57cec5SDimitry Andric 
3330b57cec5SDimitry Andric   if (PyUnicode_Check(py_obj))
3340b57cec5SDimitry Andric     return true;
3350b57cec5SDimitry Andric #if PY_MAJOR_VERSION < 3
3360b57cec5SDimitry Andric   if (PyString_Check(py_obj))
3370b57cec5SDimitry Andric     return true;
3380b57cec5SDimitry Andric #endif
3390b57cec5SDimitry Andric   return false;
3400b57cec5SDimitry Andric }
3410b57cec5SDimitry Andric 
342*9dba64beSDimitry Andric void PythonString::Convert(PyRefType &type, PyObject *&py_obj) {
3430b57cec5SDimitry Andric #if PY_MAJOR_VERSION < 3
3440b57cec5SDimitry Andric   // In Python 2, Don't store PyUnicode objects directly, because we need
3450b57cec5SDimitry Andric   // access to their underlying character buffers which Python 2 doesn't
3460b57cec5SDimitry Andric   // provide.
347*9dba64beSDimitry Andric   if (PyUnicode_Check(py_obj)) {
348*9dba64beSDimitry Andric     PyObject *s = PyUnicode_AsUTF8String(py_obj);
349*9dba64beSDimitry Andric     if (s == nullptr) {
350*9dba64beSDimitry Andric       PyErr_Clear();
351*9dba64beSDimitry Andric       if (type == PyRefType::Owned)
352*9dba64beSDimitry Andric         Py_DECREF(py_obj);
353*9dba64beSDimitry Andric       return;
354*9dba64beSDimitry Andric     }
355*9dba64beSDimitry Andric     if (type == PyRefType::Owned)
356*9dba64beSDimitry Andric       Py_DECREF(py_obj);
357*9dba64beSDimitry Andric     else
358*9dba64beSDimitry Andric       type = PyRefType::Owned;
359*9dba64beSDimitry Andric     py_obj = s;
360*9dba64beSDimitry Andric   }
3610b57cec5SDimitry Andric #endif
3620b57cec5SDimitry Andric }
3630b57cec5SDimitry Andric 
3640b57cec5SDimitry Andric llvm::StringRef PythonString::GetString() const {
365*9dba64beSDimitry Andric   auto s = AsUTF8();
366*9dba64beSDimitry Andric   if (!s) {
367*9dba64beSDimitry Andric     llvm::consumeError(s.takeError());
368*9dba64beSDimitry Andric     return llvm::StringRef("");
369*9dba64beSDimitry Andric   }
370*9dba64beSDimitry Andric   return s.get();
371*9dba64beSDimitry Andric }
372*9dba64beSDimitry Andric 
373*9dba64beSDimitry Andric Expected<llvm::StringRef> PythonString::AsUTF8() const {
3740b57cec5SDimitry Andric   if (!IsValid())
375*9dba64beSDimitry Andric     return nullDeref();
3760b57cec5SDimitry Andric 
3770b57cec5SDimitry Andric   Py_ssize_t size;
3780b57cec5SDimitry Andric   const char *data;
3790b57cec5SDimitry Andric 
3800b57cec5SDimitry Andric #if PY_MAJOR_VERSION >= 3
3810b57cec5SDimitry Andric   data = PyUnicode_AsUTF8AndSize(m_py_obj, &size);
3820b57cec5SDimitry Andric #else
383*9dba64beSDimitry Andric   char *c = NULL;
384*9dba64beSDimitry Andric   int r = PyString_AsStringAndSize(m_py_obj, &c, &size);
385*9dba64beSDimitry Andric   if (r < 0)
386*9dba64beSDimitry Andric     c = NULL;
3870b57cec5SDimitry Andric   data = c;
3880b57cec5SDimitry Andric #endif
389*9dba64beSDimitry Andric 
390*9dba64beSDimitry Andric   if (!data)
391*9dba64beSDimitry Andric     return exception();
392*9dba64beSDimitry Andric 
3930b57cec5SDimitry Andric   return llvm::StringRef(data, size);
3940b57cec5SDimitry Andric }
3950b57cec5SDimitry Andric 
3960b57cec5SDimitry Andric size_t PythonString::GetSize() const {
3970b57cec5SDimitry Andric   if (IsValid()) {
3980b57cec5SDimitry Andric #if PY_MAJOR_VERSION >= 3
3990b57cec5SDimitry Andric     return PyUnicode_GetSize(m_py_obj);
4000b57cec5SDimitry Andric #else
4010b57cec5SDimitry Andric     return PyString_Size(m_py_obj);
4020b57cec5SDimitry Andric #endif
4030b57cec5SDimitry Andric   }
4040b57cec5SDimitry Andric   return 0;
4050b57cec5SDimitry Andric }
4060b57cec5SDimitry Andric 
4070b57cec5SDimitry Andric void PythonString::SetString(llvm::StringRef string) {
408*9dba64beSDimitry Andric   auto s = FromUTF8(string);
409*9dba64beSDimitry Andric   if (!s) {
410*9dba64beSDimitry Andric     llvm::consumeError(s.takeError());
411*9dba64beSDimitry Andric     Reset();
412*9dba64beSDimitry Andric   } else {
413*9dba64beSDimitry Andric     *this = std::move(s.get());
414*9dba64beSDimitry Andric   }
4150b57cec5SDimitry Andric }
4160b57cec5SDimitry Andric 
4170b57cec5SDimitry Andric StructuredData::StringSP PythonString::CreateStructuredString() const {
4180b57cec5SDimitry Andric   StructuredData::StringSP result(new StructuredData::String);
4190b57cec5SDimitry Andric   result->SetValue(GetString());
4200b57cec5SDimitry Andric   return result;
4210b57cec5SDimitry Andric }
4220b57cec5SDimitry Andric 
4230b57cec5SDimitry Andric // PythonInteger
4240b57cec5SDimitry Andric 
425*9dba64beSDimitry Andric PythonInteger::PythonInteger(int64_t value) { SetInteger(value); }
4260b57cec5SDimitry Andric 
4270b57cec5SDimitry Andric bool PythonInteger::Check(PyObject *py_obj) {
4280b57cec5SDimitry Andric   if (!py_obj)
4290b57cec5SDimitry Andric     return false;
4300b57cec5SDimitry Andric 
4310b57cec5SDimitry Andric #if PY_MAJOR_VERSION >= 3
4320b57cec5SDimitry Andric   // Python 3 does not have PyInt_Check.  There is only one type of integral
4330b57cec5SDimitry Andric   // value, long.
4340b57cec5SDimitry Andric   return PyLong_Check(py_obj);
4350b57cec5SDimitry Andric #else
4360b57cec5SDimitry Andric   return PyLong_Check(py_obj) || PyInt_Check(py_obj);
4370b57cec5SDimitry Andric #endif
4380b57cec5SDimitry Andric }
4390b57cec5SDimitry Andric 
440*9dba64beSDimitry Andric void PythonInteger::Convert(PyRefType &type, PyObject *&py_obj) {
4410b57cec5SDimitry Andric #if PY_MAJOR_VERSION < 3
4420b57cec5SDimitry Andric   // Always store this as a PyLong, which makes interoperability between Python
4430b57cec5SDimitry Andric   // 2.x and Python 3.x easier.  This is only necessary in 2.x, since 3.x
4440b57cec5SDimitry Andric   // doesn't even have a PyInt.
4450b57cec5SDimitry Andric   if (PyInt_Check(py_obj)) {
4460b57cec5SDimitry Andric     // Since we converted the original object to a different type, the new
4470b57cec5SDimitry Andric     // object is an owned object regardless of the ownership semantics
4480b57cec5SDimitry Andric     // requested by the user.
449*9dba64beSDimitry Andric     long long value = PyInt_AsLong(py_obj);
450*9dba64beSDimitry Andric     PyObject *l = nullptr;
451*9dba64beSDimitry Andric     if (!PyErr_Occurred())
452*9dba64beSDimitry Andric       l = PyLong_FromLongLong(value);
453*9dba64beSDimitry Andric     if (l == nullptr) {
454*9dba64beSDimitry Andric       PyErr_Clear();
455*9dba64beSDimitry Andric       if (type == PyRefType::Owned)
456*9dba64beSDimitry Andric         Py_DECREF(py_obj);
457*9dba64beSDimitry Andric       return;
458*9dba64beSDimitry Andric     }
459*9dba64beSDimitry Andric     if (type == PyRefType::Owned)
460*9dba64beSDimitry Andric       Py_DECREF(py_obj);
461*9dba64beSDimitry Andric     else
462*9dba64beSDimitry Andric       type = PyRefType::Owned;
463*9dba64beSDimitry Andric     py_obj = l;
4640b57cec5SDimitry Andric   }
4650b57cec5SDimitry Andric #endif
4660b57cec5SDimitry Andric }
4670b57cec5SDimitry Andric 
4680b57cec5SDimitry Andric int64_t PythonInteger::GetInteger() const {
4690b57cec5SDimitry Andric   if (m_py_obj) {
4700b57cec5SDimitry Andric     assert(PyLong_Check(m_py_obj) &&
4710b57cec5SDimitry Andric            "PythonInteger::GetInteger has a PyObject that isn't a PyLong");
4720b57cec5SDimitry Andric 
4730b57cec5SDimitry Andric     int overflow = 0;
4740b57cec5SDimitry Andric     int64_t result = PyLong_AsLongLongAndOverflow(m_py_obj, &overflow);
4750b57cec5SDimitry Andric     if (overflow != 0) {
4760b57cec5SDimitry Andric       // We got an integer that overflows, like 18446744072853913392L we can't
4770b57cec5SDimitry Andric       // use PyLong_AsLongLong() as it will return 0xffffffffffffffff. If we
4780b57cec5SDimitry Andric       // use the unsigned long long it will work as expected.
4790b57cec5SDimitry Andric       const uint64_t uval = PyLong_AsUnsignedLongLong(m_py_obj);
4800b57cec5SDimitry Andric       result = static_cast<int64_t>(uval);
4810b57cec5SDimitry Andric     }
4820b57cec5SDimitry Andric     return result;
4830b57cec5SDimitry Andric   }
4840b57cec5SDimitry Andric   return UINT64_MAX;
4850b57cec5SDimitry Andric }
4860b57cec5SDimitry Andric 
4870b57cec5SDimitry Andric void PythonInteger::SetInteger(int64_t value) {
488*9dba64beSDimitry Andric   *this = Take<PythonInteger>(PyLong_FromLongLong(value));
4890b57cec5SDimitry Andric }
4900b57cec5SDimitry Andric 
4910b57cec5SDimitry Andric StructuredData::IntegerSP PythonInteger::CreateStructuredInteger() const {
4920b57cec5SDimitry Andric   StructuredData::IntegerSP result(new StructuredData::Integer);
4930b57cec5SDimitry Andric   result->SetValue(GetInteger());
4940b57cec5SDimitry Andric   return result;
4950b57cec5SDimitry Andric }
4960b57cec5SDimitry Andric 
4970b57cec5SDimitry Andric // PythonBoolean
4980b57cec5SDimitry Andric 
4990b57cec5SDimitry Andric PythonBoolean::PythonBoolean(bool value) {
5000b57cec5SDimitry Andric   SetValue(value);
5010b57cec5SDimitry Andric }
5020b57cec5SDimitry Andric 
5030b57cec5SDimitry Andric bool PythonBoolean::Check(PyObject *py_obj) {
5040b57cec5SDimitry Andric   return py_obj ? PyBool_Check(py_obj) : false;
5050b57cec5SDimitry Andric }
5060b57cec5SDimitry Andric 
5070b57cec5SDimitry Andric bool PythonBoolean::GetValue() const {
5080b57cec5SDimitry Andric   return m_py_obj ? PyObject_IsTrue(m_py_obj) : false;
5090b57cec5SDimitry Andric }
5100b57cec5SDimitry Andric 
5110b57cec5SDimitry Andric void PythonBoolean::SetValue(bool value) {
512*9dba64beSDimitry Andric   *this = Take<PythonBoolean>(PyBool_FromLong(value));
5130b57cec5SDimitry Andric }
5140b57cec5SDimitry Andric 
5150b57cec5SDimitry Andric StructuredData::BooleanSP PythonBoolean::CreateStructuredBoolean() const {
5160b57cec5SDimitry Andric   StructuredData::BooleanSP result(new StructuredData::Boolean);
5170b57cec5SDimitry Andric   result->SetValue(GetValue());
5180b57cec5SDimitry Andric   return result;
5190b57cec5SDimitry Andric }
5200b57cec5SDimitry Andric 
5210b57cec5SDimitry Andric // PythonList
5220b57cec5SDimitry Andric 
523*9dba64beSDimitry Andric PythonList::PythonList(PyInitialValue value) {
5240b57cec5SDimitry Andric   if (value == PyInitialValue::Empty)
525*9dba64beSDimitry Andric     *this = Take<PythonList>(PyList_New(0));
5260b57cec5SDimitry Andric }
5270b57cec5SDimitry Andric 
528*9dba64beSDimitry Andric PythonList::PythonList(int list_size) {
529*9dba64beSDimitry Andric   *this = Take<PythonList>(PyList_New(list_size));
5300b57cec5SDimitry Andric }
5310b57cec5SDimitry Andric 
5320b57cec5SDimitry Andric bool PythonList::Check(PyObject *py_obj) {
5330b57cec5SDimitry Andric   if (!py_obj)
5340b57cec5SDimitry Andric     return false;
5350b57cec5SDimitry Andric   return PyList_Check(py_obj);
5360b57cec5SDimitry Andric }
5370b57cec5SDimitry Andric 
5380b57cec5SDimitry Andric uint32_t PythonList::GetSize() const {
5390b57cec5SDimitry Andric   if (IsValid())
5400b57cec5SDimitry Andric     return PyList_GET_SIZE(m_py_obj);
5410b57cec5SDimitry Andric   return 0;
5420b57cec5SDimitry Andric }
5430b57cec5SDimitry Andric 
5440b57cec5SDimitry Andric PythonObject PythonList::GetItemAtIndex(uint32_t index) const {
5450b57cec5SDimitry Andric   if (IsValid())
5460b57cec5SDimitry Andric     return PythonObject(PyRefType::Borrowed, PyList_GetItem(m_py_obj, index));
5470b57cec5SDimitry Andric   return PythonObject();
5480b57cec5SDimitry Andric }
5490b57cec5SDimitry Andric 
5500b57cec5SDimitry Andric void PythonList::SetItemAtIndex(uint32_t index, const PythonObject &object) {
5510b57cec5SDimitry Andric   if (IsAllocated() && object.IsValid()) {
5520b57cec5SDimitry Andric     // PyList_SetItem is documented to "steal" a reference, so we need to
5530b57cec5SDimitry Andric     // convert it to an owned reference by incrementing it.
5540b57cec5SDimitry Andric     Py_INCREF(object.get());
5550b57cec5SDimitry Andric     PyList_SetItem(m_py_obj, index, object.get());
5560b57cec5SDimitry Andric   }
5570b57cec5SDimitry Andric }
5580b57cec5SDimitry Andric 
5590b57cec5SDimitry Andric void PythonList::AppendItem(const PythonObject &object) {
5600b57cec5SDimitry Andric   if (IsAllocated() && object.IsValid()) {
5610b57cec5SDimitry Andric     // `PyList_Append` does *not* steal a reference, so do not call `Py_INCREF`
5620b57cec5SDimitry Andric     // here like we do with `PyList_SetItem`.
5630b57cec5SDimitry Andric     PyList_Append(m_py_obj, object.get());
5640b57cec5SDimitry Andric   }
5650b57cec5SDimitry Andric }
5660b57cec5SDimitry Andric 
5670b57cec5SDimitry Andric StructuredData::ArraySP PythonList::CreateStructuredArray() const {
5680b57cec5SDimitry Andric   StructuredData::ArraySP result(new StructuredData::Array);
5690b57cec5SDimitry Andric   uint32_t count = GetSize();
5700b57cec5SDimitry Andric   for (uint32_t i = 0; i < count; ++i) {
5710b57cec5SDimitry Andric     PythonObject obj = GetItemAtIndex(i);
5720b57cec5SDimitry Andric     result->AddItem(obj.CreateStructuredObject());
5730b57cec5SDimitry Andric   }
5740b57cec5SDimitry Andric   return result;
5750b57cec5SDimitry Andric }
5760b57cec5SDimitry Andric 
5770b57cec5SDimitry Andric // PythonTuple
5780b57cec5SDimitry Andric 
579*9dba64beSDimitry Andric PythonTuple::PythonTuple(PyInitialValue value) {
5800b57cec5SDimitry Andric   if (value == PyInitialValue::Empty)
581*9dba64beSDimitry Andric     *this = Take<PythonTuple>(PyTuple_New(0));
5820b57cec5SDimitry Andric }
5830b57cec5SDimitry Andric 
584*9dba64beSDimitry Andric PythonTuple::PythonTuple(int tuple_size) {
585*9dba64beSDimitry Andric   *this = Take<PythonTuple>(PyTuple_New(tuple_size));
5860b57cec5SDimitry Andric }
5870b57cec5SDimitry Andric 
5880b57cec5SDimitry Andric PythonTuple::PythonTuple(std::initializer_list<PythonObject> objects) {
5890b57cec5SDimitry Andric   m_py_obj = PyTuple_New(objects.size());
5900b57cec5SDimitry Andric 
5910b57cec5SDimitry Andric   uint32_t idx = 0;
5920b57cec5SDimitry Andric   for (auto object : objects) {
5930b57cec5SDimitry Andric     if (object.IsValid())
5940b57cec5SDimitry Andric       SetItemAtIndex(idx, object);
5950b57cec5SDimitry Andric     idx++;
5960b57cec5SDimitry Andric   }
5970b57cec5SDimitry Andric }
5980b57cec5SDimitry Andric 
5990b57cec5SDimitry Andric PythonTuple::PythonTuple(std::initializer_list<PyObject *> objects) {
6000b57cec5SDimitry Andric   m_py_obj = PyTuple_New(objects.size());
6010b57cec5SDimitry Andric 
6020b57cec5SDimitry Andric   uint32_t idx = 0;
6030b57cec5SDimitry Andric   for (auto py_object : objects) {
6040b57cec5SDimitry Andric     PythonObject object(PyRefType::Borrowed, py_object);
6050b57cec5SDimitry Andric     if (object.IsValid())
6060b57cec5SDimitry Andric       SetItemAtIndex(idx, object);
6070b57cec5SDimitry Andric     idx++;
6080b57cec5SDimitry Andric   }
6090b57cec5SDimitry Andric }
6100b57cec5SDimitry Andric 
6110b57cec5SDimitry Andric bool PythonTuple::Check(PyObject *py_obj) {
6120b57cec5SDimitry Andric   if (!py_obj)
6130b57cec5SDimitry Andric     return false;
6140b57cec5SDimitry Andric   return PyTuple_Check(py_obj);
6150b57cec5SDimitry Andric }
6160b57cec5SDimitry Andric 
6170b57cec5SDimitry Andric uint32_t PythonTuple::GetSize() const {
6180b57cec5SDimitry Andric   if (IsValid())
6190b57cec5SDimitry Andric     return PyTuple_GET_SIZE(m_py_obj);
6200b57cec5SDimitry Andric   return 0;
6210b57cec5SDimitry Andric }
6220b57cec5SDimitry Andric 
6230b57cec5SDimitry Andric PythonObject PythonTuple::GetItemAtIndex(uint32_t index) const {
6240b57cec5SDimitry Andric   if (IsValid())
6250b57cec5SDimitry Andric     return PythonObject(PyRefType::Borrowed, PyTuple_GetItem(m_py_obj, index));
6260b57cec5SDimitry Andric   return PythonObject();
6270b57cec5SDimitry Andric }
6280b57cec5SDimitry Andric 
6290b57cec5SDimitry Andric void PythonTuple::SetItemAtIndex(uint32_t index, const PythonObject &object) {
6300b57cec5SDimitry Andric   if (IsAllocated() && object.IsValid()) {
6310b57cec5SDimitry Andric     // PyTuple_SetItem is documented to "steal" a reference, so we need to
6320b57cec5SDimitry Andric     // convert it to an owned reference by incrementing it.
6330b57cec5SDimitry Andric     Py_INCREF(object.get());
6340b57cec5SDimitry Andric     PyTuple_SetItem(m_py_obj, index, object.get());
6350b57cec5SDimitry Andric   }
6360b57cec5SDimitry Andric }
6370b57cec5SDimitry Andric 
6380b57cec5SDimitry Andric StructuredData::ArraySP PythonTuple::CreateStructuredArray() const {
6390b57cec5SDimitry Andric   StructuredData::ArraySP result(new StructuredData::Array);
6400b57cec5SDimitry Andric   uint32_t count = GetSize();
6410b57cec5SDimitry Andric   for (uint32_t i = 0; i < count; ++i) {
6420b57cec5SDimitry Andric     PythonObject obj = GetItemAtIndex(i);
6430b57cec5SDimitry Andric     result->AddItem(obj.CreateStructuredObject());
6440b57cec5SDimitry Andric   }
6450b57cec5SDimitry Andric   return result;
6460b57cec5SDimitry Andric }
6470b57cec5SDimitry Andric 
6480b57cec5SDimitry Andric // PythonDictionary
6490b57cec5SDimitry Andric 
650*9dba64beSDimitry Andric PythonDictionary::PythonDictionary(PyInitialValue value) {
6510b57cec5SDimitry Andric   if (value == PyInitialValue::Empty)
652*9dba64beSDimitry Andric     *this = Take<PythonDictionary>(PyDict_New());
6530b57cec5SDimitry Andric }
6540b57cec5SDimitry Andric 
6550b57cec5SDimitry Andric bool PythonDictionary::Check(PyObject *py_obj) {
6560b57cec5SDimitry Andric   if (!py_obj)
6570b57cec5SDimitry Andric     return false;
6580b57cec5SDimitry Andric 
6590b57cec5SDimitry Andric   return PyDict_Check(py_obj);
6600b57cec5SDimitry Andric }
6610b57cec5SDimitry Andric 
6620b57cec5SDimitry Andric uint32_t PythonDictionary::GetSize() const {
6630b57cec5SDimitry Andric   if (IsValid())
6640b57cec5SDimitry Andric     return PyDict_Size(m_py_obj);
6650b57cec5SDimitry Andric   return 0;
6660b57cec5SDimitry Andric }
6670b57cec5SDimitry Andric 
6680b57cec5SDimitry Andric PythonList PythonDictionary::GetKeys() const {
6690b57cec5SDimitry Andric   if (IsValid())
6700b57cec5SDimitry Andric     return PythonList(PyRefType::Owned, PyDict_Keys(m_py_obj));
6710b57cec5SDimitry Andric   return PythonList(PyInitialValue::Invalid);
6720b57cec5SDimitry Andric }
6730b57cec5SDimitry Andric 
6740b57cec5SDimitry Andric PythonObject PythonDictionary::GetItemForKey(const PythonObject &key) const {
675*9dba64beSDimitry Andric   auto item = GetItem(key);
676*9dba64beSDimitry Andric   if (!item) {
677*9dba64beSDimitry Andric     llvm::consumeError(item.takeError());
6780b57cec5SDimitry Andric     return PythonObject();
6790b57cec5SDimitry Andric   }
680*9dba64beSDimitry Andric   return std::move(item.get());
681*9dba64beSDimitry Andric }
682*9dba64beSDimitry Andric 
683*9dba64beSDimitry Andric Expected<PythonObject>
684*9dba64beSDimitry Andric PythonDictionary::GetItem(const PythonObject &key) const {
685*9dba64beSDimitry Andric   if (!IsValid())
686*9dba64beSDimitry Andric     return nullDeref();
687*9dba64beSDimitry Andric #if PY_MAJOR_VERSION >= 3
688*9dba64beSDimitry Andric   PyObject *o = PyDict_GetItemWithError(m_py_obj, key.get());
689*9dba64beSDimitry Andric   if (PyErr_Occurred())
690*9dba64beSDimitry Andric     return exception();
691*9dba64beSDimitry Andric #else
692*9dba64beSDimitry Andric   PyObject *o = PyDict_GetItem(m_py_obj, key.get());
693*9dba64beSDimitry Andric #endif
694*9dba64beSDimitry Andric   if (!o)
695*9dba64beSDimitry Andric     return keyError();
696*9dba64beSDimitry Andric   return Retain<PythonObject>(o);
697*9dba64beSDimitry Andric }
698*9dba64beSDimitry Andric 
699*9dba64beSDimitry Andric Expected<PythonObject> PythonDictionary::GetItem(const Twine &key) const {
700*9dba64beSDimitry Andric   if (!IsValid())
701*9dba64beSDimitry Andric     return nullDeref();
702*9dba64beSDimitry Andric   PyObject *o = PyDict_GetItemString(m_py_obj, NullTerminated(key));
703*9dba64beSDimitry Andric   if (PyErr_Occurred())
704*9dba64beSDimitry Andric     return exception();
705*9dba64beSDimitry Andric   if (!o)
706*9dba64beSDimitry Andric     return keyError();
707*9dba64beSDimitry Andric   return Retain<PythonObject>(o);
708*9dba64beSDimitry Andric }
709*9dba64beSDimitry Andric 
710*9dba64beSDimitry Andric Error PythonDictionary::SetItem(const PythonObject &key,
711*9dba64beSDimitry Andric                                 const PythonObject &value) const {
712*9dba64beSDimitry Andric   if (!IsValid() || !value.IsValid())
713*9dba64beSDimitry Andric     return nullDeref();
714*9dba64beSDimitry Andric   int r = PyDict_SetItem(m_py_obj, key.get(), value.get());
715*9dba64beSDimitry Andric   if (r < 0)
716*9dba64beSDimitry Andric     return exception();
717*9dba64beSDimitry Andric   return Error::success();
718*9dba64beSDimitry Andric }
719*9dba64beSDimitry Andric 
720*9dba64beSDimitry Andric Error PythonDictionary::SetItem(const Twine &key,
721*9dba64beSDimitry Andric                                 const PythonObject &value) const {
722*9dba64beSDimitry Andric   if (!IsValid() || !value.IsValid())
723*9dba64beSDimitry Andric     return nullDeref();
724*9dba64beSDimitry Andric   int r = PyDict_SetItemString(m_py_obj, NullTerminated(key), value.get());
725*9dba64beSDimitry Andric   if (r < 0)
726*9dba64beSDimitry Andric     return exception();
727*9dba64beSDimitry Andric   return Error::success();
728*9dba64beSDimitry Andric }
7290b57cec5SDimitry Andric 
7300b57cec5SDimitry Andric void PythonDictionary::SetItemForKey(const PythonObject &key,
7310b57cec5SDimitry Andric                                      const PythonObject &value) {
732*9dba64beSDimitry Andric   Error error = SetItem(key, value);
733*9dba64beSDimitry Andric   if (error)
734*9dba64beSDimitry Andric     llvm::consumeError(std::move(error));
7350b57cec5SDimitry Andric }
7360b57cec5SDimitry Andric 
7370b57cec5SDimitry Andric StructuredData::DictionarySP
7380b57cec5SDimitry Andric PythonDictionary::CreateStructuredDictionary() const {
7390b57cec5SDimitry Andric   StructuredData::DictionarySP result(new StructuredData::Dictionary);
7400b57cec5SDimitry Andric   PythonList keys(GetKeys());
7410b57cec5SDimitry Andric   uint32_t num_keys = keys.GetSize();
7420b57cec5SDimitry Andric   for (uint32_t i = 0; i < num_keys; ++i) {
7430b57cec5SDimitry Andric     PythonObject key = keys.GetItemAtIndex(i);
7440b57cec5SDimitry Andric     PythonObject value = GetItemForKey(key);
7450b57cec5SDimitry Andric     StructuredData::ObjectSP structured_value = value.CreateStructuredObject();
7460b57cec5SDimitry Andric     result->AddItem(key.Str().GetString(), structured_value);
7470b57cec5SDimitry Andric   }
7480b57cec5SDimitry Andric   return result;
7490b57cec5SDimitry Andric }
7500b57cec5SDimitry Andric 
7510b57cec5SDimitry Andric PythonModule PythonModule::BuiltinsModule() {
7520b57cec5SDimitry Andric #if PY_MAJOR_VERSION >= 3
7530b57cec5SDimitry Andric   return AddModule("builtins");
7540b57cec5SDimitry Andric #else
7550b57cec5SDimitry Andric   return AddModule("__builtin__");
7560b57cec5SDimitry Andric #endif
7570b57cec5SDimitry Andric }
7580b57cec5SDimitry Andric 
7590b57cec5SDimitry Andric PythonModule PythonModule::MainModule() { return AddModule("__main__"); }
7600b57cec5SDimitry Andric 
7610b57cec5SDimitry Andric PythonModule PythonModule::AddModule(llvm::StringRef module) {
7620b57cec5SDimitry Andric   std::string str = module.str();
7630b57cec5SDimitry Andric   return PythonModule(PyRefType::Borrowed, PyImport_AddModule(str.c_str()));
7640b57cec5SDimitry Andric }
7650b57cec5SDimitry Andric 
766*9dba64beSDimitry Andric Expected<PythonModule> PythonModule::Import(const Twine &name) {
767*9dba64beSDimitry Andric   PyObject *mod = PyImport_ImportModule(NullTerminated(name));
768*9dba64beSDimitry Andric   if (!mod)
769*9dba64beSDimitry Andric     return exception();
770*9dba64beSDimitry Andric   return Take<PythonModule>(mod);
771*9dba64beSDimitry Andric }
772*9dba64beSDimitry Andric 
773*9dba64beSDimitry Andric Expected<PythonObject> PythonModule::Get(const Twine &name) {
774*9dba64beSDimitry Andric   if (!IsValid())
775*9dba64beSDimitry Andric     return nullDeref();
776*9dba64beSDimitry Andric   PyObject *dict = PyModule_GetDict(m_py_obj);
777*9dba64beSDimitry Andric   if (!dict)
778*9dba64beSDimitry Andric     return exception();
779*9dba64beSDimitry Andric   PyObject *item = PyDict_GetItemString(dict, NullTerminated(name));
780*9dba64beSDimitry Andric   if (!item)
781*9dba64beSDimitry Andric     return exception();
782*9dba64beSDimitry Andric   return Retain<PythonObject>(item);
7830b57cec5SDimitry Andric }
7840b57cec5SDimitry Andric 
7850b57cec5SDimitry Andric bool PythonModule::Check(PyObject *py_obj) {
7860b57cec5SDimitry Andric   if (!py_obj)
7870b57cec5SDimitry Andric     return false;
7880b57cec5SDimitry Andric 
7890b57cec5SDimitry Andric   return PyModule_Check(py_obj);
7900b57cec5SDimitry Andric }
7910b57cec5SDimitry Andric 
7920b57cec5SDimitry Andric PythonDictionary PythonModule::GetDictionary() const {
793*9dba64beSDimitry Andric   if (!IsValid())
794*9dba64beSDimitry Andric     return PythonDictionary();
795*9dba64beSDimitry Andric   return Retain<PythonDictionary>(PyModule_GetDict(m_py_obj));
7960b57cec5SDimitry Andric }
7970b57cec5SDimitry Andric 
7980b57cec5SDimitry Andric bool PythonCallable::Check(PyObject *py_obj) {
7990b57cec5SDimitry Andric   if (!py_obj)
8000b57cec5SDimitry Andric     return false;
8010b57cec5SDimitry Andric 
8020b57cec5SDimitry Andric   return PyCallable_Check(py_obj);
8030b57cec5SDimitry Andric }
8040b57cec5SDimitry Andric 
805*9dba64beSDimitry Andric PythonCallable::ArgInfo PythonCallable::GetNumInitArguments() const {
806*9dba64beSDimitry Andric   auto arginfo = GetInitArgInfo();
807*9dba64beSDimitry Andric   if (!arginfo) {
808*9dba64beSDimitry Andric     llvm::consumeError(arginfo.takeError());
809*9dba64beSDimitry Andric     return ArgInfo{};
810*9dba64beSDimitry Andric   }
811*9dba64beSDimitry Andric   return arginfo.get();
8120b57cec5SDimitry Andric }
8130b57cec5SDimitry Andric 
814*9dba64beSDimitry Andric Expected<PythonCallable::ArgInfo> PythonCallable::GetInitArgInfo() const {
8150b57cec5SDimitry Andric   if (!IsValid())
816*9dba64beSDimitry Andric     return nullDeref();
817*9dba64beSDimitry Andric   auto init = As<PythonCallable>(GetAttribute("__init__"));
818*9dba64beSDimitry Andric   if (!init)
819*9dba64beSDimitry Andric     return init.takeError();
820*9dba64beSDimitry Andric   return init.get().GetArgInfo();
821*9dba64beSDimitry Andric }
8220b57cec5SDimitry Andric 
823*9dba64beSDimitry Andric #if PY_MAJOR_VERSION >= 3 && PY_MINOR_VERSION >= 3
824*9dba64beSDimitry Andric static const char get_arg_info_script[] = R"(
825*9dba64beSDimitry Andric from inspect import signature, Parameter, ismethod
826*9dba64beSDimitry Andric from collections import namedtuple
827*9dba64beSDimitry Andric ArgInfo = namedtuple('ArgInfo', ['count', 'has_varargs', 'is_bound_method'])
828*9dba64beSDimitry Andric def main(f):
829*9dba64beSDimitry Andric     count = 0
830*9dba64beSDimitry Andric     varargs = False
831*9dba64beSDimitry Andric     for parameter in signature(f).parameters.values():
832*9dba64beSDimitry Andric         kind = parameter.kind
833*9dba64beSDimitry Andric         if kind in (Parameter.POSITIONAL_ONLY,
834*9dba64beSDimitry Andric                     Parameter.POSITIONAL_OR_KEYWORD):
835*9dba64beSDimitry Andric             count += 1
836*9dba64beSDimitry Andric         elif kind == Parameter.VAR_POSITIONAL:
837*9dba64beSDimitry Andric             varargs = True
838*9dba64beSDimitry Andric         elif kind in (Parameter.KEYWORD_ONLY,
839*9dba64beSDimitry Andric                       Parameter.VAR_KEYWORD):
840*9dba64beSDimitry Andric             pass
841*9dba64beSDimitry Andric         else:
842*9dba64beSDimitry Andric             raise Exception(f'unknown parameter kind: {kind}')
843*9dba64beSDimitry Andric     return ArgInfo(count, varargs, ismethod(f))
844*9dba64beSDimitry Andric )";
845*9dba64beSDimitry Andric #endif
846*9dba64beSDimitry Andric 
847*9dba64beSDimitry Andric Expected<PythonCallable::ArgInfo> PythonCallable::GetArgInfo() const {
848*9dba64beSDimitry Andric   ArgInfo result = {};
849*9dba64beSDimitry Andric   if (!IsValid())
850*9dba64beSDimitry Andric     return nullDeref();
851*9dba64beSDimitry Andric 
852*9dba64beSDimitry Andric #if PY_MAJOR_VERSION >= 3 && PY_MINOR_VERSION >= 3
853*9dba64beSDimitry Andric 
854*9dba64beSDimitry Andric   // no need to synchronize access to this global, we already have the GIL
855*9dba64beSDimitry Andric   static PythonScript get_arg_info(get_arg_info_script);
856*9dba64beSDimitry Andric   Expected<PythonObject> pyarginfo = get_arg_info(*this);
857*9dba64beSDimitry Andric   if (!pyarginfo)
858*9dba64beSDimitry Andric     return pyarginfo.takeError();
859*9dba64beSDimitry Andric   result.count = cantFail(As<long long>(pyarginfo.get().GetAttribute("count")));
860*9dba64beSDimitry Andric   result.has_varargs =
861*9dba64beSDimitry Andric       cantFail(As<bool>(pyarginfo.get().GetAttribute("has_varargs")));
862*9dba64beSDimitry Andric   bool is_method =
863*9dba64beSDimitry Andric       cantFail(As<bool>(pyarginfo.get().GetAttribute("is_bound_method")));
864*9dba64beSDimitry Andric   result.max_positional_args =
865*9dba64beSDimitry Andric       result.has_varargs ? ArgInfo::UNBOUNDED : result.count;
866*9dba64beSDimitry Andric 
867*9dba64beSDimitry Andric   // FIXME emulate old broken behavior
868*9dba64beSDimitry Andric   if (is_method)
869*9dba64beSDimitry Andric     result.count++;
870*9dba64beSDimitry Andric 
871*9dba64beSDimitry Andric #else
872*9dba64beSDimitry Andric   bool is_bound_method = false;
8730b57cec5SDimitry Andric   PyObject *py_func_obj = m_py_obj;
8740b57cec5SDimitry Andric   if (PyMethod_Check(py_func_obj)) {
8750b57cec5SDimitry Andric     py_func_obj = PyMethod_GET_FUNCTION(py_func_obj);
8760b57cec5SDimitry Andric     PythonObject im_self = GetAttributeValue("im_self");
8770b57cec5SDimitry Andric     if (im_self.IsValid() && !im_self.IsNone())
878*9dba64beSDimitry Andric       is_bound_method = true;
8790b57cec5SDimitry Andric   } else {
8800b57cec5SDimitry Andric     // see if this is a callable object with an __call__ method
8810b57cec5SDimitry Andric     if (!PyFunction_Check(py_func_obj)) {
8820b57cec5SDimitry Andric       PythonObject __call__ = GetAttributeValue("__call__");
8830b57cec5SDimitry Andric       if (__call__.IsValid()) {
8840b57cec5SDimitry Andric         auto __callable__ = __call__.AsType<PythonCallable>();
8850b57cec5SDimitry Andric         if (__callable__.IsValid()) {
8860b57cec5SDimitry Andric           py_func_obj = PyMethod_GET_FUNCTION(__callable__.get());
887*9dba64beSDimitry Andric           PythonObject im_self = __callable__.GetAttributeValue("im_self");
8880b57cec5SDimitry Andric           if (im_self.IsValid() && !im_self.IsNone())
889*9dba64beSDimitry Andric             is_bound_method = true;
8900b57cec5SDimitry Andric         }
8910b57cec5SDimitry Andric       }
8920b57cec5SDimitry Andric     }
8930b57cec5SDimitry Andric   }
8940b57cec5SDimitry Andric 
8950b57cec5SDimitry Andric   if (!py_func_obj)
8960b57cec5SDimitry Andric     return result;
8970b57cec5SDimitry Andric 
8980b57cec5SDimitry Andric   PyCodeObject *code = (PyCodeObject *)PyFunction_GET_CODE(py_func_obj);
8990b57cec5SDimitry Andric   if (!code)
9000b57cec5SDimitry Andric     return result;
9010b57cec5SDimitry Andric 
9020b57cec5SDimitry Andric   result.count = code->co_argcount;
9030b57cec5SDimitry Andric   result.has_varargs = !!(code->co_flags & CO_VARARGS);
904*9dba64beSDimitry Andric   result.max_positional_args = result.has_varargs
905*9dba64beSDimitry Andric                                    ? ArgInfo::UNBOUNDED
906*9dba64beSDimitry Andric                                    : (result.count - (int)is_bound_method);
907*9dba64beSDimitry Andric 
908*9dba64beSDimitry Andric #endif
909*9dba64beSDimitry Andric 
9100b57cec5SDimitry Andric   return result;
9110b57cec5SDimitry Andric }
9120b57cec5SDimitry Andric 
913*9dba64beSDimitry Andric constexpr unsigned
914*9dba64beSDimitry Andric     PythonCallable::ArgInfo::UNBOUNDED; // FIXME delete after c++17
915*9dba64beSDimitry Andric 
916*9dba64beSDimitry Andric PythonCallable::ArgInfo PythonCallable::GetNumArguments() const {
917*9dba64beSDimitry Andric   auto arginfo = GetArgInfo();
918*9dba64beSDimitry Andric   if (!arginfo) {
919*9dba64beSDimitry Andric     llvm::consumeError(arginfo.takeError());
920*9dba64beSDimitry Andric     return ArgInfo{};
921*9dba64beSDimitry Andric   }
922*9dba64beSDimitry Andric   return arginfo.get();
923*9dba64beSDimitry Andric }
924*9dba64beSDimitry Andric 
9250b57cec5SDimitry Andric PythonObject PythonCallable::operator()() {
9260b57cec5SDimitry Andric   return PythonObject(PyRefType::Owned, PyObject_CallObject(m_py_obj, nullptr));
9270b57cec5SDimitry Andric }
9280b57cec5SDimitry Andric 
9290b57cec5SDimitry Andric PythonObject PythonCallable::
9300b57cec5SDimitry Andric operator()(std::initializer_list<PyObject *> args) {
9310b57cec5SDimitry Andric   PythonTuple arg_tuple(args);
9320b57cec5SDimitry Andric   return PythonObject(PyRefType::Owned,
9330b57cec5SDimitry Andric                       PyObject_CallObject(m_py_obj, arg_tuple.get()));
9340b57cec5SDimitry Andric }
9350b57cec5SDimitry Andric 
9360b57cec5SDimitry Andric PythonObject PythonCallable::
9370b57cec5SDimitry Andric operator()(std::initializer_list<PythonObject> args) {
9380b57cec5SDimitry Andric   PythonTuple arg_tuple(args);
9390b57cec5SDimitry Andric   return PythonObject(PyRefType::Owned,
9400b57cec5SDimitry Andric                       PyObject_CallObject(m_py_obj, arg_tuple.get()));
9410b57cec5SDimitry Andric }
9420b57cec5SDimitry Andric 
9430b57cec5SDimitry Andric bool PythonFile::Check(PyObject *py_obj) {
944*9dba64beSDimitry Andric   if (!py_obj)
945*9dba64beSDimitry Andric     return false;
9460b57cec5SDimitry Andric #if PY_MAJOR_VERSION < 3
9470b57cec5SDimitry Andric   return PyFile_Check(py_obj);
9480b57cec5SDimitry Andric #else
9490b57cec5SDimitry Andric   // In Python 3, there is no `PyFile_Check`, and in fact PyFile is not even a
9500b57cec5SDimitry Andric   // first-class object type anymore.  `PyFile_FromFd` is just a thin wrapper
9510b57cec5SDimitry Andric   // over `io.open()`, which returns some object derived from `io.IOBase`. As a
9520b57cec5SDimitry Andric   // result, the only way to detect a file in Python 3 is to check whether it
953*9dba64beSDimitry Andric   // inherits from `io.IOBase`.
954*9dba64beSDimitry Andric   auto io_module = PythonModule::Import("io");
955*9dba64beSDimitry Andric   if (!io_module) {
956*9dba64beSDimitry Andric     llvm::consumeError(io_module.takeError());
9570b57cec5SDimitry Andric     return false;
958*9dba64beSDimitry Andric   }
959*9dba64beSDimitry Andric   auto iobase = io_module.get().Get("IOBase");
960*9dba64beSDimitry Andric   if (!iobase) {
961*9dba64beSDimitry Andric     llvm::consumeError(iobase.takeError());
9620b57cec5SDimitry Andric     return false;
963*9dba64beSDimitry Andric   }
964*9dba64beSDimitry Andric   int r = PyObject_IsInstance(py_obj, iobase.get().get());
965*9dba64beSDimitry Andric   if (r < 0) {
966*9dba64beSDimitry Andric     llvm::consumeError(exception()); // clear the exception and log it.
967*9dba64beSDimitry Andric     return false;
968*9dba64beSDimitry Andric   }
969*9dba64beSDimitry Andric   return !!r;
9700b57cec5SDimitry Andric #endif
9710b57cec5SDimitry Andric }
9720b57cec5SDimitry Andric 
973*9dba64beSDimitry Andric namespace {
974*9dba64beSDimitry Andric class GIL {
975*9dba64beSDimitry Andric public:
976*9dba64beSDimitry Andric   GIL() {
977*9dba64beSDimitry Andric     m_state = PyGILState_Ensure();
978*9dba64beSDimitry Andric     assert(!PyErr_Occurred());
979*9dba64beSDimitry Andric   }
980*9dba64beSDimitry Andric   ~GIL() { PyGILState_Release(m_state); }
9810b57cec5SDimitry Andric 
982*9dba64beSDimitry Andric protected:
983*9dba64beSDimitry Andric   PyGILState_STATE m_state;
984*9dba64beSDimitry Andric };
985*9dba64beSDimitry Andric } // namespace
986*9dba64beSDimitry Andric 
987*9dba64beSDimitry Andric const char *PythonException::toCString() const {
988*9dba64beSDimitry Andric   if (!m_repr_bytes)
989*9dba64beSDimitry Andric     return "unknown exception";
990*9dba64beSDimitry Andric   return PyBytes_AS_STRING(m_repr_bytes);
9910b57cec5SDimitry Andric }
9920b57cec5SDimitry Andric 
993*9dba64beSDimitry Andric PythonException::PythonException(const char *caller) {
994*9dba64beSDimitry Andric   assert(PyErr_Occurred());
995*9dba64beSDimitry Andric   m_exception_type = m_exception = m_traceback = m_repr_bytes = NULL;
996*9dba64beSDimitry Andric   PyErr_Fetch(&m_exception_type, &m_exception, &m_traceback);
997*9dba64beSDimitry Andric   PyErr_NormalizeException(&m_exception_type, &m_exception, &m_traceback);
998*9dba64beSDimitry Andric   PyErr_Clear();
999*9dba64beSDimitry Andric   if (m_exception) {
1000*9dba64beSDimitry Andric     PyObject *repr = PyObject_Repr(m_exception);
1001*9dba64beSDimitry Andric     if (repr) {
1002*9dba64beSDimitry Andric       m_repr_bytes = PyUnicode_AsEncodedString(repr, "utf-8", nullptr);
1003*9dba64beSDimitry Andric       if (!m_repr_bytes) {
1004*9dba64beSDimitry Andric         PyErr_Clear();
1005*9dba64beSDimitry Andric       }
1006*9dba64beSDimitry Andric       Py_XDECREF(repr);
1007*9dba64beSDimitry Andric     } else {
1008*9dba64beSDimitry Andric       PyErr_Clear();
1009*9dba64beSDimitry Andric     }
1010*9dba64beSDimitry Andric   }
1011*9dba64beSDimitry Andric   Log *log = GetLogIfAllCategoriesSet(LIBLLDB_LOG_SCRIPT);
1012*9dba64beSDimitry Andric   if (caller)
1013*9dba64beSDimitry Andric     LLDB_LOGF(log, "%s failed with exception: %s", caller, toCString());
1014*9dba64beSDimitry Andric   else
1015*9dba64beSDimitry Andric     LLDB_LOGF(log, "python exception: %s", toCString());
1016*9dba64beSDimitry Andric }
1017*9dba64beSDimitry Andric void PythonException::Restore() {
1018*9dba64beSDimitry Andric   if (m_exception_type && m_exception) {
1019*9dba64beSDimitry Andric     PyErr_Restore(m_exception_type, m_exception, m_traceback);
1020*9dba64beSDimitry Andric   } else {
1021*9dba64beSDimitry Andric     PyErr_SetString(PyExc_Exception, toCString());
1022*9dba64beSDimitry Andric   }
1023*9dba64beSDimitry Andric   m_exception_type = m_exception = m_traceback = NULL;
10240b57cec5SDimitry Andric }
10250b57cec5SDimitry Andric 
1026*9dba64beSDimitry Andric PythonException::~PythonException() {
1027*9dba64beSDimitry Andric   Py_XDECREF(m_exception_type);
1028*9dba64beSDimitry Andric   Py_XDECREF(m_exception);
1029*9dba64beSDimitry Andric   Py_XDECREF(m_traceback);
1030*9dba64beSDimitry Andric   Py_XDECREF(m_repr_bytes);
10310b57cec5SDimitry Andric }
10320b57cec5SDimitry Andric 
1033*9dba64beSDimitry Andric void PythonException::log(llvm::raw_ostream &OS) const { OS << toCString(); }
1034*9dba64beSDimitry Andric 
1035*9dba64beSDimitry Andric std::error_code PythonException::convertToErrorCode() const {
1036*9dba64beSDimitry Andric   return llvm::inconvertibleErrorCode();
1037*9dba64beSDimitry Andric }
1038*9dba64beSDimitry Andric 
1039*9dba64beSDimitry Andric bool PythonException::Matches(PyObject *exc) const {
1040*9dba64beSDimitry Andric   return PyErr_GivenExceptionMatches(m_exception_type, exc);
1041*9dba64beSDimitry Andric }
1042*9dba64beSDimitry Andric 
1043*9dba64beSDimitry Andric const char read_exception_script[] = R"(
1044*9dba64beSDimitry Andric import sys
1045*9dba64beSDimitry Andric from traceback import print_exception
1046*9dba64beSDimitry Andric if sys.version_info.major < 3:
1047*9dba64beSDimitry Andric   from StringIO import StringIO
1048*9dba64beSDimitry Andric else:
1049*9dba64beSDimitry Andric   from io import StringIO
1050*9dba64beSDimitry Andric def main(exc_type, exc_value, tb):
1051*9dba64beSDimitry Andric   f = StringIO()
1052*9dba64beSDimitry Andric   print_exception(exc_type, exc_value, tb, file=f)
1053*9dba64beSDimitry Andric   return f.getvalue()
1054*9dba64beSDimitry Andric )";
1055*9dba64beSDimitry Andric 
1056*9dba64beSDimitry Andric std::string PythonException::ReadBacktrace() const {
1057*9dba64beSDimitry Andric 
1058*9dba64beSDimitry Andric   if (!m_traceback)
1059*9dba64beSDimitry Andric     return toCString();
1060*9dba64beSDimitry Andric 
1061*9dba64beSDimitry Andric   // no need to synchronize access to this global, we already have the GIL
1062*9dba64beSDimitry Andric   static PythonScript read_exception(read_exception_script);
1063*9dba64beSDimitry Andric 
1064*9dba64beSDimitry Andric   Expected<std::string> backtrace = As<std::string>(
1065*9dba64beSDimitry Andric       read_exception(m_exception_type, m_exception, m_traceback));
1066*9dba64beSDimitry Andric 
1067*9dba64beSDimitry Andric   if (!backtrace) {
1068*9dba64beSDimitry Andric     std::string message =
1069*9dba64beSDimitry Andric         std::string(toCString()) + "\n" +
1070*9dba64beSDimitry Andric         "Traceback unavailble, an error occurred while reading it:\n";
1071*9dba64beSDimitry Andric     return (message + llvm::toString(backtrace.takeError()));
1072*9dba64beSDimitry Andric   }
1073*9dba64beSDimitry Andric 
1074*9dba64beSDimitry Andric   return std::move(backtrace.get());
1075*9dba64beSDimitry Andric }
1076*9dba64beSDimitry Andric 
1077*9dba64beSDimitry Andric char PythonException::ID = 0;
1078*9dba64beSDimitry Andric 
1079*9dba64beSDimitry Andric llvm::Expected<File::OpenOptions>
1080*9dba64beSDimitry Andric GetOptionsForPyObject(const PythonObject &obj) {
10810b57cec5SDimitry Andric #if PY_MAJOR_VERSION >= 3
1082*9dba64beSDimitry Andric   auto options = File::OpenOptions(0);
1083*9dba64beSDimitry Andric   auto readable = As<bool>(obj.CallMethod("readable"));
1084*9dba64beSDimitry Andric   if (!readable)
1085*9dba64beSDimitry Andric     return readable.takeError();
1086*9dba64beSDimitry Andric   auto writable = As<bool>(obj.CallMethod("writable"));
1087*9dba64beSDimitry Andric   if (!writable)
1088*9dba64beSDimitry Andric     return writable.takeError();
1089*9dba64beSDimitry Andric   if (readable.get())
1090*9dba64beSDimitry Andric     options |= File::eOpenOptionRead;
1091*9dba64beSDimitry Andric   if (writable.get())
1092*9dba64beSDimitry Andric     options |= File::eOpenOptionWrite;
1093*9dba64beSDimitry Andric   return options;
1094*9dba64beSDimitry Andric #else
1095*9dba64beSDimitry Andric   PythonString py_mode = obj.GetAttributeValue("mode").AsType<PythonString>();
1096*9dba64beSDimitry Andric   return File::GetOptionsFromMode(py_mode.GetString());
1097*9dba64beSDimitry Andric #endif
1098*9dba64beSDimitry Andric }
1099*9dba64beSDimitry Andric 
1100*9dba64beSDimitry Andric // Base class template for python files.   All it knows how to do
1101*9dba64beSDimitry Andric // is hold a reference to the python object and close or flush it
1102*9dba64beSDimitry Andric // when the File is closed.
1103*9dba64beSDimitry Andric namespace {
1104*9dba64beSDimitry Andric template <typename Base> class OwnedPythonFile : public Base {
1105*9dba64beSDimitry Andric public:
1106*9dba64beSDimitry Andric   template <typename... Args>
1107*9dba64beSDimitry Andric   OwnedPythonFile(const PythonFile &file, bool borrowed, Args... args)
1108*9dba64beSDimitry Andric       : Base(args...), m_py_obj(file), m_borrowed(borrowed) {
1109*9dba64beSDimitry Andric     assert(m_py_obj);
1110*9dba64beSDimitry Andric   }
1111*9dba64beSDimitry Andric 
1112*9dba64beSDimitry Andric   ~OwnedPythonFile() override {
1113*9dba64beSDimitry Andric     assert(m_py_obj);
1114*9dba64beSDimitry Andric     GIL takeGIL;
1115*9dba64beSDimitry Andric     Close();
1116*9dba64beSDimitry Andric     // we need to ensure the python object is released while we still
1117*9dba64beSDimitry Andric     // hold the GIL
1118*9dba64beSDimitry Andric     m_py_obj.Reset();
1119*9dba64beSDimitry Andric   }
1120*9dba64beSDimitry Andric 
1121*9dba64beSDimitry Andric   bool IsPythonSideValid() const {
1122*9dba64beSDimitry Andric     GIL takeGIL;
1123*9dba64beSDimitry Andric     auto closed = As<bool>(m_py_obj.GetAttribute("closed"));
1124*9dba64beSDimitry Andric     if (!closed) {
1125*9dba64beSDimitry Andric       llvm::consumeError(closed.takeError());
1126*9dba64beSDimitry Andric       return false;
1127*9dba64beSDimitry Andric     }
1128*9dba64beSDimitry Andric     return !closed.get();
1129*9dba64beSDimitry Andric   }
1130*9dba64beSDimitry Andric 
1131*9dba64beSDimitry Andric   bool IsValid() const override {
1132*9dba64beSDimitry Andric     return IsPythonSideValid() && Base::IsValid();
1133*9dba64beSDimitry Andric   }
1134*9dba64beSDimitry Andric 
1135*9dba64beSDimitry Andric   Status Close() override {
1136*9dba64beSDimitry Andric     assert(m_py_obj);
1137*9dba64beSDimitry Andric     Status py_error, base_error;
1138*9dba64beSDimitry Andric     GIL takeGIL;
1139*9dba64beSDimitry Andric     if (!m_borrowed) {
1140*9dba64beSDimitry Andric       auto r = m_py_obj.CallMethod("close");
1141*9dba64beSDimitry Andric       if (!r)
1142*9dba64beSDimitry Andric         py_error = Status(r.takeError());
1143*9dba64beSDimitry Andric     }
1144*9dba64beSDimitry Andric     base_error = Base::Close();
1145*9dba64beSDimitry Andric     if (py_error.Fail())
1146*9dba64beSDimitry Andric       return py_error;
1147*9dba64beSDimitry Andric     return base_error;
1148*9dba64beSDimitry Andric   };
1149*9dba64beSDimitry Andric 
1150*9dba64beSDimitry Andric   PyObject *GetPythonObject() const {
1151*9dba64beSDimitry Andric     assert(m_py_obj.IsValid());
1152*9dba64beSDimitry Andric     return m_py_obj.get();
1153*9dba64beSDimitry Andric   }
1154*9dba64beSDimitry Andric 
1155*9dba64beSDimitry Andric   static bool classof(const File *file) = delete;
1156*9dba64beSDimitry Andric 
1157*9dba64beSDimitry Andric protected:
1158*9dba64beSDimitry Andric   PythonFile m_py_obj;
1159*9dba64beSDimitry Andric   bool m_borrowed;
1160*9dba64beSDimitry Andric };
1161*9dba64beSDimitry Andric } // namespace
1162*9dba64beSDimitry Andric 
1163*9dba64beSDimitry Andric // A SimplePythonFile is a OwnedPythonFile that just does all I/O as
1164*9dba64beSDimitry Andric // a NativeFile
1165*9dba64beSDimitry Andric namespace {
1166*9dba64beSDimitry Andric class SimplePythonFile : public OwnedPythonFile<NativeFile> {
1167*9dba64beSDimitry Andric public:
1168*9dba64beSDimitry Andric   SimplePythonFile(const PythonFile &file, bool borrowed, int fd,
1169*9dba64beSDimitry Andric                    File::OpenOptions options)
1170*9dba64beSDimitry Andric       : OwnedPythonFile(file, borrowed, fd, options, false) {}
1171*9dba64beSDimitry Andric 
1172*9dba64beSDimitry Andric   static char ID;
1173*9dba64beSDimitry Andric   bool isA(const void *classID) const override {
1174*9dba64beSDimitry Andric     return classID == &ID || NativeFile::isA(classID);
1175*9dba64beSDimitry Andric   }
1176*9dba64beSDimitry Andric   static bool classof(const File *file) { return file->isA(&ID); }
1177*9dba64beSDimitry Andric };
1178*9dba64beSDimitry Andric char SimplePythonFile::ID = 0;
1179*9dba64beSDimitry Andric } // namespace
1180*9dba64beSDimitry Andric 
1181*9dba64beSDimitry Andric #if PY_MAJOR_VERSION >= 3
1182*9dba64beSDimitry Andric 
1183*9dba64beSDimitry Andric namespace {
1184*9dba64beSDimitry Andric class PythonBuffer {
1185*9dba64beSDimitry Andric public:
1186*9dba64beSDimitry Andric   PythonBuffer &operator=(const PythonBuffer &) = delete;
1187*9dba64beSDimitry Andric   PythonBuffer(const PythonBuffer &) = delete;
1188*9dba64beSDimitry Andric 
1189*9dba64beSDimitry Andric   static Expected<PythonBuffer> Create(PythonObject &obj,
1190*9dba64beSDimitry Andric                                        int flags = PyBUF_SIMPLE) {
1191*9dba64beSDimitry Andric     Py_buffer py_buffer = {};
1192*9dba64beSDimitry Andric     PyObject_GetBuffer(obj.get(), &py_buffer, flags);
1193*9dba64beSDimitry Andric     if (!py_buffer.obj)
1194*9dba64beSDimitry Andric       return llvm::make_error<PythonException>();
1195*9dba64beSDimitry Andric     return PythonBuffer(py_buffer);
1196*9dba64beSDimitry Andric   }
1197*9dba64beSDimitry Andric 
1198*9dba64beSDimitry Andric   PythonBuffer(PythonBuffer &&other) {
1199*9dba64beSDimitry Andric     m_buffer = other.m_buffer;
1200*9dba64beSDimitry Andric     other.m_buffer.obj = nullptr;
1201*9dba64beSDimitry Andric   }
1202*9dba64beSDimitry Andric 
1203*9dba64beSDimitry Andric   ~PythonBuffer() {
1204*9dba64beSDimitry Andric     if (m_buffer.obj)
1205*9dba64beSDimitry Andric       PyBuffer_Release(&m_buffer);
1206*9dba64beSDimitry Andric   }
1207*9dba64beSDimitry Andric 
1208*9dba64beSDimitry Andric   Py_buffer &get() { return m_buffer; }
1209*9dba64beSDimitry Andric 
1210*9dba64beSDimitry Andric private:
1211*9dba64beSDimitry Andric   // takes ownership of the buffer.
1212*9dba64beSDimitry Andric   PythonBuffer(const Py_buffer &py_buffer) : m_buffer(py_buffer) {}
1213*9dba64beSDimitry Andric   Py_buffer m_buffer;
1214*9dba64beSDimitry Andric };
1215*9dba64beSDimitry Andric } // namespace
1216*9dba64beSDimitry Andric 
1217*9dba64beSDimitry Andric // Shared methods between TextPythonFile and BinaryPythonFile
1218*9dba64beSDimitry Andric namespace {
1219*9dba64beSDimitry Andric class PythonIOFile : public OwnedPythonFile<File> {
1220*9dba64beSDimitry Andric public:
1221*9dba64beSDimitry Andric   PythonIOFile(const PythonFile &file, bool borrowed)
1222*9dba64beSDimitry Andric       : OwnedPythonFile(file, borrowed) {}
1223*9dba64beSDimitry Andric 
1224*9dba64beSDimitry Andric   ~PythonIOFile() override { Close(); }
1225*9dba64beSDimitry Andric 
1226*9dba64beSDimitry Andric   bool IsValid() const override { return IsPythonSideValid(); }
1227*9dba64beSDimitry Andric 
1228*9dba64beSDimitry Andric   Status Close() override {
1229*9dba64beSDimitry Andric     assert(m_py_obj);
1230*9dba64beSDimitry Andric     GIL takeGIL;
1231*9dba64beSDimitry Andric     if (m_borrowed)
1232*9dba64beSDimitry Andric       return Flush();
1233*9dba64beSDimitry Andric     auto r = m_py_obj.CallMethod("close");
1234*9dba64beSDimitry Andric     if (!r)
1235*9dba64beSDimitry Andric       return Status(r.takeError());
1236*9dba64beSDimitry Andric     return Status();
1237*9dba64beSDimitry Andric   }
1238*9dba64beSDimitry Andric 
1239*9dba64beSDimitry Andric   Status Flush() override {
1240*9dba64beSDimitry Andric     GIL takeGIL;
1241*9dba64beSDimitry Andric     auto r = m_py_obj.CallMethod("flush");
1242*9dba64beSDimitry Andric     if (!r)
1243*9dba64beSDimitry Andric       return Status(r.takeError());
1244*9dba64beSDimitry Andric     return Status();
1245*9dba64beSDimitry Andric   }
1246*9dba64beSDimitry Andric 
1247*9dba64beSDimitry Andric   Expected<File::OpenOptions> GetOptions() const override {
1248*9dba64beSDimitry Andric     GIL takeGIL;
1249*9dba64beSDimitry Andric     return GetOptionsForPyObject(m_py_obj);
1250*9dba64beSDimitry Andric   }
1251*9dba64beSDimitry Andric 
1252*9dba64beSDimitry Andric   static char ID;
1253*9dba64beSDimitry Andric   bool isA(const void *classID) const override {
1254*9dba64beSDimitry Andric     return classID == &ID || File::isA(classID);
1255*9dba64beSDimitry Andric   }
1256*9dba64beSDimitry Andric   static bool classof(const File *file) { return file->isA(&ID); }
1257*9dba64beSDimitry Andric };
1258*9dba64beSDimitry Andric char PythonIOFile::ID = 0;
1259*9dba64beSDimitry Andric } // namespace
1260*9dba64beSDimitry Andric 
1261*9dba64beSDimitry Andric namespace {
1262*9dba64beSDimitry Andric class BinaryPythonFile : public PythonIOFile {
1263*9dba64beSDimitry Andric protected:
1264*9dba64beSDimitry Andric   int m_descriptor;
1265*9dba64beSDimitry Andric 
1266*9dba64beSDimitry Andric public:
1267*9dba64beSDimitry Andric   BinaryPythonFile(int fd, const PythonFile &file, bool borrowed)
1268*9dba64beSDimitry Andric       : PythonIOFile(file, borrowed),
1269*9dba64beSDimitry Andric         m_descriptor(File::DescriptorIsValid(fd) ? fd
1270*9dba64beSDimitry Andric                                                  : File::kInvalidDescriptor) {}
1271*9dba64beSDimitry Andric 
1272*9dba64beSDimitry Andric   int GetDescriptor() const override { return m_descriptor; }
1273*9dba64beSDimitry Andric 
1274*9dba64beSDimitry Andric   Status Write(const void *buf, size_t &num_bytes) override {
1275*9dba64beSDimitry Andric     GIL takeGIL;
1276*9dba64beSDimitry Andric     PyObject *pybuffer_p = PyMemoryView_FromMemory(
1277*9dba64beSDimitry Andric         const_cast<char *>((const char *)buf), num_bytes, PyBUF_READ);
1278*9dba64beSDimitry Andric     if (!pybuffer_p)
1279*9dba64beSDimitry Andric       return Status(llvm::make_error<PythonException>());
1280*9dba64beSDimitry Andric     auto pybuffer = Take<PythonObject>(pybuffer_p);
1281*9dba64beSDimitry Andric     num_bytes = 0;
1282*9dba64beSDimitry Andric     auto bytes_written = As<long long>(m_py_obj.CallMethod("write", pybuffer));
1283*9dba64beSDimitry Andric     if (!bytes_written)
1284*9dba64beSDimitry Andric       return Status(bytes_written.takeError());
1285*9dba64beSDimitry Andric     if (bytes_written.get() < 0)
1286*9dba64beSDimitry Andric       return Status(".write() method returned a negative number!");
1287*9dba64beSDimitry Andric     static_assert(sizeof(long long) >= sizeof(size_t), "overflow");
1288*9dba64beSDimitry Andric     num_bytes = bytes_written.get();
1289*9dba64beSDimitry Andric     return Status();
1290*9dba64beSDimitry Andric   }
1291*9dba64beSDimitry Andric 
1292*9dba64beSDimitry Andric   Status Read(void *buf, size_t &num_bytes) override {
1293*9dba64beSDimitry Andric     GIL takeGIL;
1294*9dba64beSDimitry Andric     static_assert(sizeof(long long) >= sizeof(size_t), "overflow");
1295*9dba64beSDimitry Andric     auto pybuffer_obj =
1296*9dba64beSDimitry Andric         m_py_obj.CallMethod("read", (unsigned long long)num_bytes);
1297*9dba64beSDimitry Andric     if (!pybuffer_obj)
1298*9dba64beSDimitry Andric       return Status(pybuffer_obj.takeError());
1299*9dba64beSDimitry Andric     num_bytes = 0;
1300*9dba64beSDimitry Andric     if (pybuffer_obj.get().IsNone()) {
1301*9dba64beSDimitry Andric       // EOF
1302*9dba64beSDimitry Andric       num_bytes = 0;
1303*9dba64beSDimitry Andric       return Status();
1304*9dba64beSDimitry Andric     }
1305*9dba64beSDimitry Andric     auto pybuffer = PythonBuffer::Create(pybuffer_obj.get());
1306*9dba64beSDimitry Andric     if (!pybuffer)
1307*9dba64beSDimitry Andric       return Status(pybuffer.takeError());
1308*9dba64beSDimitry Andric     memcpy(buf, pybuffer.get().get().buf, pybuffer.get().get().len);
1309*9dba64beSDimitry Andric     num_bytes = pybuffer.get().get().len;
1310*9dba64beSDimitry Andric     return Status();
1311*9dba64beSDimitry Andric   }
1312*9dba64beSDimitry Andric };
1313*9dba64beSDimitry Andric } // namespace
1314*9dba64beSDimitry Andric 
1315*9dba64beSDimitry Andric namespace {
1316*9dba64beSDimitry Andric class TextPythonFile : public PythonIOFile {
1317*9dba64beSDimitry Andric protected:
1318*9dba64beSDimitry Andric   int m_descriptor;
1319*9dba64beSDimitry Andric 
1320*9dba64beSDimitry Andric public:
1321*9dba64beSDimitry Andric   TextPythonFile(int fd, const PythonFile &file, bool borrowed)
1322*9dba64beSDimitry Andric       : PythonIOFile(file, borrowed),
1323*9dba64beSDimitry Andric         m_descriptor(File::DescriptorIsValid(fd) ? fd
1324*9dba64beSDimitry Andric                                                  : File::kInvalidDescriptor) {}
1325*9dba64beSDimitry Andric 
1326*9dba64beSDimitry Andric   int GetDescriptor() const override { return m_descriptor; }
1327*9dba64beSDimitry Andric 
1328*9dba64beSDimitry Andric   Status Write(const void *buf, size_t &num_bytes) override {
1329*9dba64beSDimitry Andric     GIL takeGIL;
1330*9dba64beSDimitry Andric     auto pystring =
1331*9dba64beSDimitry Andric         PythonString::FromUTF8(llvm::StringRef((const char *)buf, num_bytes));
1332*9dba64beSDimitry Andric     if (!pystring)
1333*9dba64beSDimitry Andric       return Status(pystring.takeError());
1334*9dba64beSDimitry Andric     num_bytes = 0;
1335*9dba64beSDimitry Andric     auto bytes_written =
1336*9dba64beSDimitry Andric         As<long long>(m_py_obj.CallMethod("write", pystring.get()));
1337*9dba64beSDimitry Andric     if (!bytes_written)
1338*9dba64beSDimitry Andric       return Status(bytes_written.takeError());
1339*9dba64beSDimitry Andric     if (bytes_written.get() < 0)
1340*9dba64beSDimitry Andric       return Status(".write() method returned a negative number!");
1341*9dba64beSDimitry Andric     static_assert(sizeof(long long) >= sizeof(size_t), "overflow");
1342*9dba64beSDimitry Andric     num_bytes = bytes_written.get();
1343*9dba64beSDimitry Andric     return Status();
1344*9dba64beSDimitry Andric   }
1345*9dba64beSDimitry Andric 
1346*9dba64beSDimitry Andric   Status Read(void *buf, size_t &num_bytes) override {
1347*9dba64beSDimitry Andric     GIL takeGIL;
1348*9dba64beSDimitry Andric     size_t num_chars = num_bytes / 6;
1349*9dba64beSDimitry Andric     size_t orig_num_bytes = num_bytes;
1350*9dba64beSDimitry Andric     num_bytes = 0;
1351*9dba64beSDimitry Andric     if (orig_num_bytes < 6) {
1352*9dba64beSDimitry Andric       return Status("can't read less than 6 bytes from a utf8 text stream");
1353*9dba64beSDimitry Andric     }
1354*9dba64beSDimitry Andric     auto pystring = As<PythonString>(
1355*9dba64beSDimitry Andric         m_py_obj.CallMethod("read", (unsigned long long)num_chars));
1356*9dba64beSDimitry Andric     if (!pystring)
1357*9dba64beSDimitry Andric       return Status(pystring.takeError());
1358*9dba64beSDimitry Andric     if (pystring.get().IsNone()) {
1359*9dba64beSDimitry Andric       // EOF
1360*9dba64beSDimitry Andric       return Status();
1361*9dba64beSDimitry Andric     }
1362*9dba64beSDimitry Andric     auto stringref = pystring.get().AsUTF8();
1363*9dba64beSDimitry Andric     if (!stringref)
1364*9dba64beSDimitry Andric       return Status(stringref.takeError());
1365*9dba64beSDimitry Andric     num_bytes = stringref.get().size();
1366*9dba64beSDimitry Andric     memcpy(buf, stringref.get().begin(), num_bytes);
1367*9dba64beSDimitry Andric     return Status();
1368*9dba64beSDimitry Andric   }
1369*9dba64beSDimitry Andric };
1370*9dba64beSDimitry Andric } // namespace
1371*9dba64beSDimitry Andric 
1372*9dba64beSDimitry Andric #endif
1373*9dba64beSDimitry Andric 
1374*9dba64beSDimitry Andric llvm::Expected<FileSP> PythonFile::ConvertToFile(bool borrowed) {
1375*9dba64beSDimitry Andric   if (!IsValid())
1376*9dba64beSDimitry Andric     return llvm::createStringError(llvm::inconvertibleErrorCode(),
1377*9dba64beSDimitry Andric                                    "invalid PythonFile");
1378*9dba64beSDimitry Andric 
1379*9dba64beSDimitry Andric   int fd = PyObject_AsFileDescriptor(m_py_obj);
1380*9dba64beSDimitry Andric   if (fd < 0) {
1381*9dba64beSDimitry Andric     PyErr_Clear();
1382*9dba64beSDimitry Andric     return ConvertToFileForcingUseOfScriptingIOMethods(borrowed);
1383*9dba64beSDimitry Andric   }
1384*9dba64beSDimitry Andric   auto options = GetOptionsForPyObject(*this);
1385*9dba64beSDimitry Andric   if (!options)
1386*9dba64beSDimitry Andric     return options.takeError();
1387*9dba64beSDimitry Andric 
1388*9dba64beSDimitry Andric   // LLDB and python will not share I/O buffers.  We should probably
1389*9dba64beSDimitry Andric   // flush the python buffers now.
1390*9dba64beSDimitry Andric   auto r = CallMethod("flush");
1391*9dba64beSDimitry Andric   if (!r)
1392*9dba64beSDimitry Andric     return r.takeError();
1393*9dba64beSDimitry Andric 
1394*9dba64beSDimitry Andric   FileSP file_sp;
1395*9dba64beSDimitry Andric   if (borrowed) {
1396*9dba64beSDimitry Andric     // In this case we we don't need to retain the python
1397*9dba64beSDimitry Andric     // object at all.
1398*9dba64beSDimitry Andric     file_sp = std::make_shared<NativeFile>(fd, options.get(), false);
1399*9dba64beSDimitry Andric   } else {
1400*9dba64beSDimitry Andric     file_sp = std::static_pointer_cast<File>(
1401*9dba64beSDimitry Andric         std::make_shared<SimplePythonFile>(*this, borrowed, fd, options.get()));
1402*9dba64beSDimitry Andric   }
1403*9dba64beSDimitry Andric   if (!file_sp->IsValid())
1404*9dba64beSDimitry Andric     return llvm::createStringError(llvm::inconvertibleErrorCode(),
1405*9dba64beSDimitry Andric                                    "invalid File");
1406*9dba64beSDimitry Andric 
1407*9dba64beSDimitry Andric   return file_sp;
1408*9dba64beSDimitry Andric }
1409*9dba64beSDimitry Andric 
1410*9dba64beSDimitry Andric llvm::Expected<FileSP>
1411*9dba64beSDimitry Andric PythonFile::ConvertToFileForcingUseOfScriptingIOMethods(bool borrowed) {
1412*9dba64beSDimitry Andric 
1413*9dba64beSDimitry Andric   assert(!PyErr_Occurred());
1414*9dba64beSDimitry Andric 
1415*9dba64beSDimitry Andric   if (!IsValid())
1416*9dba64beSDimitry Andric     return llvm::createStringError(llvm::inconvertibleErrorCode(),
1417*9dba64beSDimitry Andric                                    "invalid PythonFile");
1418*9dba64beSDimitry Andric 
1419*9dba64beSDimitry Andric #if PY_MAJOR_VERSION < 3
1420*9dba64beSDimitry Andric 
1421*9dba64beSDimitry Andric   return llvm::createStringError(llvm::inconvertibleErrorCode(),
1422*9dba64beSDimitry Andric                                  "not supported on python 2");
1423*9dba64beSDimitry Andric 
1424*9dba64beSDimitry Andric #else
1425*9dba64beSDimitry Andric 
1426*9dba64beSDimitry Andric   int fd = PyObject_AsFileDescriptor(m_py_obj);
1427*9dba64beSDimitry Andric   if (fd < 0) {
1428*9dba64beSDimitry Andric     PyErr_Clear();
1429*9dba64beSDimitry Andric     fd = File::kInvalidDescriptor;
1430*9dba64beSDimitry Andric   }
1431*9dba64beSDimitry Andric 
1432*9dba64beSDimitry Andric   auto io_module = PythonModule::Import("io");
1433*9dba64beSDimitry Andric   if (!io_module)
1434*9dba64beSDimitry Andric     return io_module.takeError();
1435*9dba64beSDimitry Andric   auto textIOBase = io_module.get().Get("TextIOBase");
1436*9dba64beSDimitry Andric   if (!textIOBase)
1437*9dba64beSDimitry Andric     return textIOBase.takeError();
1438*9dba64beSDimitry Andric   auto rawIOBase = io_module.get().Get("RawIOBase");
1439*9dba64beSDimitry Andric   if (!rawIOBase)
1440*9dba64beSDimitry Andric     return rawIOBase.takeError();
1441*9dba64beSDimitry Andric   auto bufferedIOBase = io_module.get().Get("BufferedIOBase");
1442*9dba64beSDimitry Andric   if (!bufferedIOBase)
1443*9dba64beSDimitry Andric     return bufferedIOBase.takeError();
1444*9dba64beSDimitry Andric 
1445*9dba64beSDimitry Andric   FileSP file_sp;
1446*9dba64beSDimitry Andric 
1447*9dba64beSDimitry Andric   auto isTextIO = IsInstance(textIOBase.get());
1448*9dba64beSDimitry Andric   if (!isTextIO)
1449*9dba64beSDimitry Andric     return isTextIO.takeError();
1450*9dba64beSDimitry Andric   if (isTextIO.get())
1451*9dba64beSDimitry Andric     file_sp = std::static_pointer_cast<File>(
1452*9dba64beSDimitry Andric         std::make_shared<TextPythonFile>(fd, *this, borrowed));
1453*9dba64beSDimitry Andric 
1454*9dba64beSDimitry Andric   auto isRawIO = IsInstance(rawIOBase.get());
1455*9dba64beSDimitry Andric   if (!isRawIO)
1456*9dba64beSDimitry Andric     return isRawIO.takeError();
1457*9dba64beSDimitry Andric   auto isBufferedIO = IsInstance(bufferedIOBase.get());
1458*9dba64beSDimitry Andric   if (!isBufferedIO)
1459*9dba64beSDimitry Andric     return isBufferedIO.takeError();
1460*9dba64beSDimitry Andric 
1461*9dba64beSDimitry Andric   if (isRawIO.get() || isBufferedIO.get()) {
1462*9dba64beSDimitry Andric     file_sp = std::static_pointer_cast<File>(
1463*9dba64beSDimitry Andric         std::make_shared<BinaryPythonFile>(fd, *this, borrowed));
1464*9dba64beSDimitry Andric   }
1465*9dba64beSDimitry Andric 
1466*9dba64beSDimitry Andric   if (!file_sp)
1467*9dba64beSDimitry Andric     return llvm::createStringError(llvm::inconvertibleErrorCode(),
1468*9dba64beSDimitry Andric                                    "python file is neither text nor binary");
1469*9dba64beSDimitry Andric 
1470*9dba64beSDimitry Andric   if (!file_sp->IsValid())
1471*9dba64beSDimitry Andric     return llvm::createStringError(llvm::inconvertibleErrorCode(),
1472*9dba64beSDimitry Andric                                    "invalid File");
1473*9dba64beSDimitry Andric 
1474*9dba64beSDimitry Andric   return file_sp;
1475*9dba64beSDimitry Andric 
1476*9dba64beSDimitry Andric #endif
1477*9dba64beSDimitry Andric }
1478*9dba64beSDimitry Andric 
1479*9dba64beSDimitry Andric Expected<PythonFile> PythonFile::FromFile(File &file, const char *mode) {
1480*9dba64beSDimitry Andric   if (!file.IsValid())
1481*9dba64beSDimitry Andric     return llvm::createStringError(llvm::inconvertibleErrorCode(),
1482*9dba64beSDimitry Andric                                    "invalid file");
1483*9dba64beSDimitry Andric 
1484*9dba64beSDimitry Andric   if (auto *simple = llvm::dyn_cast<SimplePythonFile>(&file))
1485*9dba64beSDimitry Andric     return Retain<PythonFile>(simple->GetPythonObject());
1486*9dba64beSDimitry Andric #if PY_MAJOR_VERSION >= 3
1487*9dba64beSDimitry Andric   if (auto *pythonio = llvm::dyn_cast<PythonIOFile>(&file))
1488*9dba64beSDimitry Andric     return Retain<PythonFile>(pythonio->GetPythonObject());
1489*9dba64beSDimitry Andric #endif
1490*9dba64beSDimitry Andric 
1491*9dba64beSDimitry Andric   if (!mode) {
1492*9dba64beSDimitry Andric     auto m = file.GetOpenMode();
1493*9dba64beSDimitry Andric     if (!m)
1494*9dba64beSDimitry Andric       return m.takeError();
1495*9dba64beSDimitry Andric     mode = m.get();
1496*9dba64beSDimitry Andric   }
1497*9dba64beSDimitry Andric 
1498*9dba64beSDimitry Andric   PyObject *file_obj;
1499*9dba64beSDimitry Andric #if PY_MAJOR_VERSION >= 3
1500*9dba64beSDimitry Andric   file_obj = PyFile_FromFd(file.GetDescriptor(), nullptr, mode, -1, nullptr,
1501*9dba64beSDimitry Andric                            "ignore", nullptr, 0);
15020b57cec5SDimitry Andric #else
15030b57cec5SDimitry Andric   // Read through the Python source, doesn't seem to modify these strings
1504*9dba64beSDimitry Andric   char *cmode = const_cast<char *>(mode);
1505*9dba64beSDimitry Andric   // We pass ::flush instead of ::fclose here so we borrow the FILE* --
1506*9dba64beSDimitry Andric   // the lldb_private::File still owns it.
1507*9dba64beSDimitry Andric   file_obj =
1508*9dba64beSDimitry Andric       PyFile_FromFile(file.GetStream(), const_cast<char *>(""), cmode, ::fflush);
15090b57cec5SDimitry Andric #endif
1510*9dba64beSDimitry Andric 
1511*9dba64beSDimitry Andric   if (!file_obj)
1512*9dba64beSDimitry Andric     return exception();
1513*9dba64beSDimitry Andric 
1514*9dba64beSDimitry Andric   return Take<PythonFile>(file_obj);
15150b57cec5SDimitry Andric }
15160b57cec5SDimitry Andric 
1517*9dba64beSDimitry Andric Error PythonScript::Init() {
1518*9dba64beSDimitry Andric   if (function.IsValid())
1519*9dba64beSDimitry Andric     return Error::success();
15200b57cec5SDimitry Andric 
1521*9dba64beSDimitry Andric   PythonDictionary globals(PyInitialValue::Empty);
1522*9dba64beSDimitry Andric   auto builtins = PythonModule::BuiltinsModule();
1523*9dba64beSDimitry Andric   if (Error error = globals.SetItem("__builtins__", builtins))
1524*9dba64beSDimitry Andric     return error;
1525*9dba64beSDimitry Andric   PyObject *o =
1526*9dba64beSDimitry Andric       PyRun_String(script, Py_file_input, globals.get(), globals.get());
1527*9dba64beSDimitry Andric   if (!o)
1528*9dba64beSDimitry Andric     return exception();
1529*9dba64beSDimitry Andric   Take<PythonObject>(o);
1530*9dba64beSDimitry Andric   auto f = As<PythonCallable>(globals.GetItem("main"));
1531*9dba64beSDimitry Andric   if (!f)
1532*9dba64beSDimitry Andric     return f.takeError();
1533*9dba64beSDimitry Andric   function = std::move(f.get());
1534*9dba64beSDimitry Andric 
1535*9dba64beSDimitry Andric   return Error::success();
15360b57cec5SDimitry Andric }
15370b57cec5SDimitry Andric 
1538*9dba64beSDimitry Andric llvm::Expected<PythonObject>
1539*9dba64beSDimitry Andric python::runStringOneLine(const llvm::Twine &string,
1540*9dba64beSDimitry Andric                          const PythonDictionary &globals,
1541*9dba64beSDimitry Andric                          const PythonDictionary &locals) {
1542*9dba64beSDimitry Andric   if (!globals.IsValid() || !locals.IsValid())
1543*9dba64beSDimitry Andric     return nullDeref();
15440b57cec5SDimitry Andric 
1545*9dba64beSDimitry Andric   PyObject *code =
1546*9dba64beSDimitry Andric       Py_CompileString(NullTerminated(string), "<string>", Py_eval_input);
1547*9dba64beSDimitry Andric   if (!code) {
1548*9dba64beSDimitry Andric     PyErr_Clear();
1549*9dba64beSDimitry Andric     code =
1550*9dba64beSDimitry Andric         Py_CompileString(NullTerminated(string), "<string>", Py_single_input);
1551*9dba64beSDimitry Andric   }
1552*9dba64beSDimitry Andric   if (!code)
1553*9dba64beSDimitry Andric     return exception();
1554*9dba64beSDimitry Andric   auto code_ref = Take<PythonObject>(code);
1555*9dba64beSDimitry Andric 
1556*9dba64beSDimitry Andric #if PY_MAJOR_VERSION < 3
1557*9dba64beSDimitry Andric   PyObject *result =
1558*9dba64beSDimitry Andric       PyEval_EvalCode((PyCodeObject *)code, globals.get(), locals.get());
1559*9dba64beSDimitry Andric #else
1560*9dba64beSDimitry Andric   PyObject *result = PyEval_EvalCode(code, globals.get(), locals.get());
1561*9dba64beSDimitry Andric #endif
1562*9dba64beSDimitry Andric 
1563*9dba64beSDimitry Andric   if (!result)
1564*9dba64beSDimitry Andric     return exception();
1565*9dba64beSDimitry Andric 
1566*9dba64beSDimitry Andric   return Take<PythonObject>(result);
1567*9dba64beSDimitry Andric }
1568*9dba64beSDimitry Andric 
1569*9dba64beSDimitry Andric llvm::Expected<PythonObject>
1570*9dba64beSDimitry Andric python::runStringMultiLine(const llvm::Twine &string,
1571*9dba64beSDimitry Andric                            const PythonDictionary &globals,
1572*9dba64beSDimitry Andric                            const PythonDictionary &locals) {
1573*9dba64beSDimitry Andric   if (!globals.IsValid() || !locals.IsValid())
1574*9dba64beSDimitry Andric     return nullDeref();
1575*9dba64beSDimitry Andric   PyObject *result = PyRun_String(NullTerminated(string), Py_file_input,
1576*9dba64beSDimitry Andric                                   globals.get(), locals.get());
1577*9dba64beSDimitry Andric   if (!result)
1578*9dba64beSDimitry Andric     return exception();
1579*9dba64beSDimitry Andric   return Take<PythonObject>(result);
15800b57cec5SDimitry Andric }
15810b57cec5SDimitry Andric 
15820b57cec5SDimitry Andric #endif
1583