180814287SRaphael Isemann //===-- PythonDataObjects.cpp ---------------------------------------------===//
22c1f46dcSZachary Turner //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
62c1f46dcSZachary Turner //
72c1f46dcSZachary Turner //===----------------------------------------------------------------------===//
82c1f46dcSZachary Turner 
959998b7bSJonas Devlieghere #include "lldb/Host/Config.h"
10d68983e3SPavel Labath 
114e26cf2cSJonas Devlieghere #if LLDB_ENABLE_PYTHON
12d68983e3SPavel Labath 
132c1f46dcSZachary Turner #include "PythonDataObjects.h"
142c1f46dcSZachary Turner #include "ScriptInterpreterPython.h"
152c1f46dcSZachary Turner 
162c1f46dcSZachary Turner #include "lldb/Host/File.h"
17190fadcdSZachary Turner #include "lldb/Host/FileSystem.h"
182c1f46dcSZachary Turner #include "lldb/Interpreter/ScriptInterpreter.h"
19085328eeSLawrence D'Anna #include "lldb/Utility/Log.h"
20bf9a7730SZachary Turner #include "lldb/Utility/Stream.h"
212c1f46dcSZachary Turner 
229a6c7572SJonas Devlieghere #include "llvm/ADT/StringSwitch.h"
23d9b553ecSLawrence D'Anna #include "llvm/Support/Casting.h"
24190fadcdSZachary Turner #include "llvm/Support/ConvertUTF.h"
252819136fSMichal Gorny #include "llvm/Support/Errno.h"
26190fadcdSZachary Turner 
272c1f46dcSZachary Turner #include <stdio.h>
282c1f46dcSZachary Turner 
292c1f46dcSZachary Turner using namespace lldb_private;
302c1f46dcSZachary Turner using namespace lldb;
31085328eeSLawrence D'Anna using namespace lldb_private::python;
32c86a6acaSLawrence D'Anna using llvm::cantFail;
33085328eeSLawrence D'Anna using llvm::Error;
34085328eeSLawrence D'Anna using llvm::Expected;
35722b6189SLawrence D'Anna using llvm::Twine;
36085328eeSLawrence D'Anna 
37085328eeSLawrence D'Anna template <> Expected<bool> python::As<bool>(Expected<PythonObject> &&obj) {
38085328eeSLawrence D'Anna   if (!obj)
39085328eeSLawrence D'Anna     return obj.takeError();
40085328eeSLawrence D'Anna   return obj.get().IsTrue();
41085328eeSLawrence D'Anna }
42085328eeSLawrence D'Anna 
43085328eeSLawrence D'Anna template <>
44085328eeSLawrence D'Anna Expected<long long> python::As<long long>(Expected<PythonObject> &&obj) {
45085328eeSLawrence D'Anna   if (!obj)
46085328eeSLawrence D'Anna     return obj.takeError();
47*52712d3fSLawrence D'Anna   return obj->AsLongLong();
48*52712d3fSLawrence D'Anna }
49*52712d3fSLawrence D'Anna 
50*52712d3fSLawrence D'Anna template <>
51*52712d3fSLawrence D'Anna Expected<unsigned long long>
52*52712d3fSLawrence D'Anna python::As<unsigned long long>(Expected<PythonObject> &&obj) {
53*52712d3fSLawrence D'Anna   if (!obj)
54*52712d3fSLawrence D'Anna     return obj.takeError();
55*52712d3fSLawrence D'Anna   return obj->AsUnsignedLongLong();
56085328eeSLawrence D'Anna }
572c1f46dcSZachary Turner 
58c86a6acaSLawrence D'Anna template <>
59c86a6acaSLawrence D'Anna Expected<std::string> python::As<std::string>(Expected<PythonObject> &&obj) {
60c86a6acaSLawrence D'Anna   if (!obj)
61c86a6acaSLawrence D'Anna     return obj.takeError();
62c86a6acaSLawrence D'Anna   PyObject *str_obj = PyObject_Str(obj.get().get());
63c86a6acaSLawrence D'Anna   if (!obj)
64c86a6acaSLawrence D'Anna     return llvm::make_error<PythonException>();
65c86a6acaSLawrence D'Anna   auto str = Take<PythonString>(str_obj);
66c86a6acaSLawrence D'Anna   auto utf8 = str.AsUTF8();
67c86a6acaSLawrence D'Anna   if (!utf8)
68c86a6acaSLawrence D'Anna     return utf8.takeError();
6919580c37SBenjamin Kramer   return std::string(utf8.get());
70c86a6acaSLawrence D'Anna }
71c86a6acaSLawrence D'Anna 
72*52712d3fSLawrence D'Anna Expected<long long> PythonObject::AsLongLong() const {
73*52712d3fSLawrence D'Anna   if (!m_py_obj)
74*52712d3fSLawrence D'Anna     return nullDeref();
75*52712d3fSLawrence D'Anna #if PY_MAJOR_VERSION < 3
76*52712d3fSLawrence D'Anna   if (!PyLong_Check(m_py_obj)) {
77*52712d3fSLawrence D'Anna     PythonInteger i(PyRefType::Borrowed, m_py_obj);
78*52712d3fSLawrence D'Anna     return i.AsLongLong();
79*52712d3fSLawrence D'Anna   }
80*52712d3fSLawrence D'Anna #endif
81*52712d3fSLawrence D'Anna   assert(!PyErr_Occurred());
82*52712d3fSLawrence D'Anna   long long r = PyLong_AsLongLong(m_py_obj);
83*52712d3fSLawrence D'Anna   if (PyErr_Occurred())
84*52712d3fSLawrence D'Anna     return exception();
85*52712d3fSLawrence D'Anna   return r;
86*52712d3fSLawrence D'Anna }
87*52712d3fSLawrence D'Anna 
88*52712d3fSLawrence D'Anna Expected<long long> PythonObject::AsUnsignedLongLong() const {
89*52712d3fSLawrence D'Anna   if (!m_py_obj)
90*52712d3fSLawrence D'Anna     return nullDeref();
91*52712d3fSLawrence D'Anna #if PY_MAJOR_VERSION < 3
92*52712d3fSLawrence D'Anna   if (!PyLong_Check(m_py_obj)) {
93*52712d3fSLawrence D'Anna     PythonInteger i(PyRefType::Borrowed, m_py_obj);
94*52712d3fSLawrence D'Anna     return i.AsUnsignedLongLong();
95*52712d3fSLawrence D'Anna   }
96*52712d3fSLawrence D'Anna #endif
97*52712d3fSLawrence D'Anna   assert(!PyErr_Occurred());
98*52712d3fSLawrence D'Anna   long long r = PyLong_AsUnsignedLongLong(m_py_obj);
99*52712d3fSLawrence D'Anna   if (PyErr_Occurred())
100*52712d3fSLawrence D'Anna     return exception();
101*52712d3fSLawrence D'Anna   return r;
102*52712d3fSLawrence D'Anna }
103*52712d3fSLawrence D'Anna 
104*52712d3fSLawrence D'Anna // wraps on overflow, instead of raising an error.
105*52712d3fSLawrence D'Anna Expected<unsigned long long> PythonObject::AsModuloUnsignedLongLong() const {
106*52712d3fSLawrence D'Anna   if (!m_py_obj)
107*52712d3fSLawrence D'Anna     return nullDeref();
108*52712d3fSLawrence D'Anna #if PY_MAJOR_VERSION < 3
109*52712d3fSLawrence D'Anna   if (!PyLong_Check(m_py_obj)) {
110*52712d3fSLawrence D'Anna     PythonInteger i(PyRefType::Borrowed, m_py_obj);
111*52712d3fSLawrence D'Anna     return i.AsModuloUnsignedLongLong();
112*52712d3fSLawrence D'Anna   }
113*52712d3fSLawrence D'Anna #endif
114*52712d3fSLawrence D'Anna   assert(!PyErr_Occurred());
115*52712d3fSLawrence D'Anna   unsigned long long r = PyLong_AsUnsignedLongLongMask(m_py_obj);
116*52712d3fSLawrence D'Anna   if (PyErr_Occurred())
117*52712d3fSLawrence D'Anna     return exception();
118*52712d3fSLawrence D'Anna   return r;
119*52712d3fSLawrence D'Anna }
120*52712d3fSLawrence D'Anna 
1212783d817SJonas Devlieghere void StructuredPythonObject::Serialize(llvm::json::OStream &s) const {
1222783d817SJonas Devlieghere   s.value(llvm::formatv("Python Obj: {0:X}", GetValue()).str());
1232c1f46dcSZachary Turner }
1242c1f46dcSZachary Turner 
1252c1f46dcSZachary Turner // PythonObject
1262c1f46dcSZachary Turner 
127b9c1b51eSKate Stone void PythonObject::Dump(Stream &strm) const {
128b9c1b51eSKate Stone   if (m_py_obj) {
1292819136fSMichal Gorny     FILE *file = llvm::sys::RetryAfterSignal(nullptr, ::tmpfile);
130b9c1b51eSKate Stone     if (file) {
1312c1f46dcSZachary Turner       ::PyObject_Print(m_py_obj, file, 0);
1322c1f46dcSZachary Turner       const long length = ftell(file);
133b9c1b51eSKate Stone       if (length) {
1342c1f46dcSZachary Turner         ::rewind(file);
1352c1f46dcSZachary Turner         std::vector<char> file_contents(length, '\0');
136b9c1b51eSKate Stone         const size_t length_read =
137b9c1b51eSKate Stone             ::fread(file_contents.data(), 1, file_contents.size(), file);
1382c1f46dcSZachary Turner         if (length_read > 0)
1392c1f46dcSZachary Turner           strm.Write(file_contents.data(), length_read);
1402c1f46dcSZachary Turner       }
1412c1f46dcSZachary Turner       ::fclose(file);
1422c1f46dcSZachary Turner     }
143b9c1b51eSKate Stone   } else
1442c1f46dcSZachary Turner     strm.PutCString("NULL");
1452c1f46dcSZachary Turner }
1462c1f46dcSZachary Turner 
147b9c1b51eSKate Stone PyObjectType PythonObject::GetObjectType() const {
148f8b22f8fSZachary Turner   if (!IsAllocated())
1492c1f46dcSZachary Turner     return PyObjectType::None;
1502c1f46dcSZachary Turner 
1517841efbbSZachary Turner   if (PythonModule::Check(m_py_obj))
1527841efbbSZachary Turner     return PyObjectType::Module;
15318426935SZachary Turner   if (PythonList::Check(m_py_obj))
1542c1f46dcSZachary Turner     return PyObjectType::List;
155a1405147SZachary Turner   if (PythonTuple::Check(m_py_obj))
156a1405147SZachary Turner     return PyObjectType::Tuple;
15718426935SZachary Turner   if (PythonDictionary::Check(m_py_obj))
1582c1f46dcSZachary Turner     return PyObjectType::Dictionary;
15918426935SZachary Turner   if (PythonString::Check(m_py_obj))
16022c8efcdSZachary Turner     return PyObjectType::String;
1615a72c02bSZachary Turner #if PY_MAJOR_VERSION >= 3
1625a72c02bSZachary Turner   if (PythonBytes::Check(m_py_obj))
1635a72c02bSZachary Turner     return PyObjectType::Bytes;
1645a72c02bSZachary Turner #endif
165f9d6d204SZachary Turner   if (PythonByteArray::Check(m_py_obj))
166f9d6d204SZachary Turner     return PyObjectType::ByteArray;
167b81d715cSTatyana Krasnukha   if (PythonBoolean::Check(m_py_obj))
168b81d715cSTatyana Krasnukha     return PyObjectType::Boolean;
16918426935SZachary Turner   if (PythonInteger::Check(m_py_obj))
17022c8efcdSZachary Turner     return PyObjectType::Integer;
1719c40264fSZachary Turner   if (PythonFile::Check(m_py_obj))
1729c40264fSZachary Turner     return PyObjectType::File;
173a1405147SZachary Turner   if (PythonCallable::Check(m_py_obj))
174a1405147SZachary Turner     return PyObjectType::Callable;
1752c1f46dcSZachary Turner   return PyObjectType::Unknown;
1762c1f46dcSZachary Turner }
1772c1f46dcSZachary Turner 
178b9c1b51eSKate Stone PythonString PythonObject::Repr() const {
1792c1f46dcSZachary Turner   if (!m_py_obj)
1802c1f46dcSZachary Turner     return PythonString();
1812c1f46dcSZachary Turner   PyObject *repr = PyObject_Repr(m_py_obj);
1822c1f46dcSZachary Turner   if (!repr)
1832c1f46dcSZachary Turner     return PythonString();
184f8b22f8fSZachary Turner   return PythonString(PyRefType::Owned, repr);
1852c1f46dcSZachary Turner }
1862c1f46dcSZachary Turner 
187b9c1b51eSKate Stone PythonString PythonObject::Str() const {
1882c1f46dcSZachary Turner   if (!m_py_obj)
1892c1f46dcSZachary Turner     return PythonString();
1902c1f46dcSZachary Turner   PyObject *str = PyObject_Str(m_py_obj);
1912c1f46dcSZachary Turner   if (!str)
1922c1f46dcSZachary Turner     return PythonString();
193f8b22f8fSZachary Turner   return PythonString(PyRefType::Owned, str);
1942c1f46dcSZachary Turner }
1952c1f46dcSZachary Turner 
1967841efbbSZachary Turner PythonObject
197b9c1b51eSKate Stone PythonObject::ResolveNameWithDictionary(llvm::StringRef name,
198b9c1b51eSKate Stone                                         const PythonDictionary &dict) {
199c712bac7SJonas Devlieghere   size_t dot_pos = name.find('.');
200a1405147SZachary Turner   llvm::StringRef piece = name.substr(0, dot_pos);
201a1405147SZachary Turner   PythonObject result = dict.GetItemForKey(PythonString(piece));
202b9c1b51eSKate Stone   if (dot_pos == llvm::StringRef::npos) {
203a1405147SZachary Turner     // There was no dot, we're done.
204a1405147SZachary Turner     return result;
205a1405147SZachary Turner   }
206a1405147SZachary Turner 
207a1405147SZachary Turner   // There was a dot.  The remaining portion of the name should be looked up in
208a1405147SZachary Turner   // the context of the object that was found in the dictionary.
209a1405147SZachary Turner   return result.ResolveName(name.substr(dot_pos + 1));
2107841efbbSZachary Turner }
2117841efbbSZachary Turner 
212b9c1b51eSKate Stone PythonObject PythonObject::ResolveName(llvm::StringRef name) const {
21305097246SAdrian Prantl   // Resolve the name in the context of the specified object.  If, for example,
21405097246SAdrian Prantl   // `this` refers to a PyModule, then this will look for `name` in this
21505097246SAdrian Prantl   // module.  If `this` refers to a PyType, then it will resolve `name` as an
21605097246SAdrian Prantl   // attribute of that type.  If `this` refers to an instance of an object,
21705097246SAdrian Prantl   // then it will resolve `name` as the value of the specified field.
2187841efbbSZachary Turner   //
2197841efbbSZachary Turner   // This function handles dotted names so that, for example, if `m_py_obj`
22005097246SAdrian Prantl   // refers to the `sys` module, and `name` == "path.append", then it will find
22105097246SAdrian Prantl   // the function `sys.path.append`.
2227841efbbSZachary Turner 
223c712bac7SJonas Devlieghere   size_t dot_pos = name.find('.');
224b9c1b51eSKate Stone   if (dot_pos == llvm::StringRef::npos) {
22505097246SAdrian Prantl     // No dots in the name, we should be able to find the value immediately as
22605097246SAdrian Prantl     // an attribute of `m_py_obj`.
2277841efbbSZachary Turner     return GetAttributeValue(name);
2287841efbbSZachary Turner   }
2297841efbbSZachary Turner 
230b9c1b51eSKate Stone   // Look up the first piece of the name, and resolve the rest as a child of
231b9c1b51eSKate Stone   // that.
2327841efbbSZachary Turner   PythonObject parent = ResolveName(name.substr(0, dot_pos));
2337841efbbSZachary Turner   if (!parent.IsAllocated())
2347841efbbSZachary Turner     return PythonObject();
2357841efbbSZachary Turner 
2367841efbbSZachary Turner   // Tail recursion.. should be optimized by the compiler
2377841efbbSZachary Turner   return parent.ResolveName(name.substr(dot_pos + 1));
2387841efbbSZachary Turner }
2397841efbbSZachary Turner 
240b9c1b51eSKate Stone bool PythonObject::HasAttribute(llvm::StringRef attr) const {
2419c40264fSZachary Turner   if (!IsValid())
2429c40264fSZachary Turner     return false;
2439c40264fSZachary Turner   PythonString py_attr(attr);
2449c40264fSZachary Turner   return !!PyObject_HasAttr(m_py_obj, py_attr.get());
2459c40264fSZachary Turner }
2469c40264fSZachary Turner 
247b9c1b51eSKate Stone PythonObject PythonObject::GetAttributeValue(llvm::StringRef attr) const {
2487d6d218eSZachary Turner   if (!IsValid())
2497d6d218eSZachary Turner     return PythonObject();
2507d6d218eSZachary Turner 
2517d6d218eSZachary Turner   PythonString py_attr(attr);
2527d6d218eSZachary Turner   if (!PyObject_HasAttr(m_py_obj, py_attr.get()))
2537d6d218eSZachary Turner     return PythonObject();
2547d6d218eSZachary Turner 
2557d6d218eSZachary Turner   return PythonObject(PyRefType::Owned,
2567d6d218eSZachary Turner                       PyObject_GetAttr(m_py_obj, py_attr.get()));
2577d6d218eSZachary Turner }
2587d6d218eSZachary Turner 
259b9c1b51eSKate Stone StructuredData::ObjectSP PythonObject::CreateStructuredObject() const {
260b9c1b51eSKate Stone   switch (GetObjectType()) {
2612c1f46dcSZachary Turner   case PyObjectType::Dictionary:
262b9c1b51eSKate Stone     return PythonDictionary(PyRefType::Borrowed, m_py_obj)
263b9c1b51eSKate Stone         .CreateStructuredDictionary();
264b81d715cSTatyana Krasnukha   case PyObjectType::Boolean:
265b81d715cSTatyana Krasnukha     return PythonBoolean(PyRefType::Borrowed, m_py_obj)
266b81d715cSTatyana Krasnukha         .CreateStructuredBoolean();
2672c1f46dcSZachary Turner   case PyObjectType::Integer:
268b9c1b51eSKate Stone     return PythonInteger(PyRefType::Borrowed, m_py_obj)
269b9c1b51eSKate Stone         .CreateStructuredInteger();
2702c1f46dcSZachary Turner   case PyObjectType::List:
271f8b22f8fSZachary Turner     return PythonList(PyRefType::Borrowed, m_py_obj).CreateStructuredArray();
2722c1f46dcSZachary Turner   case PyObjectType::String:
273f8b22f8fSZachary Turner     return PythonString(PyRefType::Borrowed, m_py_obj).CreateStructuredString();
2745a72c02bSZachary Turner   case PyObjectType::Bytes:
2755a72c02bSZachary Turner     return PythonBytes(PyRefType::Borrowed, m_py_obj).CreateStructuredString();
276f9d6d204SZachary Turner   case PyObjectType::ByteArray:
277b9c1b51eSKate Stone     return PythonByteArray(PyRefType::Borrowed, m_py_obj)
278b9c1b51eSKate Stone         .CreateStructuredString();
2792c1f46dcSZachary Turner   case PyObjectType::None:
2802c1f46dcSZachary Turner     return StructuredData::ObjectSP();
2812c1f46dcSZachary Turner   default:
2822c1f46dcSZachary Turner     return StructuredData::ObjectSP(new StructuredPythonObject(m_py_obj));
2832c1f46dcSZachary Turner   }
2842c1f46dcSZachary Turner }
2852c1f46dcSZachary Turner 
2862c1f46dcSZachary Turner // PythonString
2875a72c02bSZachary Turner 
288d3bd5b3dSLawrence D'Anna PythonBytes::PythonBytes(llvm::ArrayRef<uint8_t> bytes) { SetBytes(bytes); }
2895a72c02bSZachary Turner 
290d3bd5b3dSLawrence D'Anna PythonBytes::PythonBytes(const uint8_t *bytes, size_t length) {
2915a72c02bSZachary Turner   SetBytes(llvm::ArrayRef<uint8_t>(bytes, length));
2925a72c02bSZachary Turner }
2935a72c02bSZachary Turner 
294b9c1b51eSKate Stone bool PythonBytes::Check(PyObject *py_obj) {
2955a72c02bSZachary Turner   if (!py_obj)
2965a72c02bSZachary Turner     return false;
297a6682a41SJonas Devlieghere   return PyBytes_Check(py_obj);
2985a72c02bSZachary Turner }
2995a72c02bSZachary Turner 
300b9c1b51eSKate Stone llvm::ArrayRef<uint8_t> PythonBytes::GetBytes() const {
3015a72c02bSZachary Turner   if (!IsValid())
3025a72c02bSZachary Turner     return llvm::ArrayRef<uint8_t>();
3035a72c02bSZachary Turner 
3045a72c02bSZachary Turner   Py_ssize_t size;
3055a72c02bSZachary Turner   char *c;
3065a72c02bSZachary Turner 
3075a72c02bSZachary Turner   PyBytes_AsStringAndSize(m_py_obj, &c, &size);
3085a72c02bSZachary Turner   return llvm::ArrayRef<uint8_t>(reinterpret_cast<uint8_t *>(c), size);
3095a72c02bSZachary Turner }
3105a72c02bSZachary Turner 
311b9c1b51eSKate Stone size_t PythonBytes::GetSize() const {
3125a72c02bSZachary Turner   if (!IsValid())
3135a72c02bSZachary Turner     return 0;
3145a72c02bSZachary Turner   return PyBytes_Size(m_py_obj);
3155a72c02bSZachary Turner }
3165a72c02bSZachary Turner 
317b9c1b51eSKate Stone void PythonBytes::SetBytes(llvm::ArrayRef<uint8_t> bytes) {
3185a72c02bSZachary Turner   const char *data = reinterpret_cast<const char *>(bytes.data());
31904edd189SLawrence D'Anna   *this = Take<PythonBytes>(PyBytes_FromStringAndSize(data, bytes.size()));
3205a72c02bSZachary Turner }
3215a72c02bSZachary Turner 
322b9c1b51eSKate Stone StructuredData::StringSP PythonBytes::CreateStructuredString() const {
3235a72c02bSZachary Turner   StructuredData::StringSP result(new StructuredData::String);
3245a72c02bSZachary Turner   Py_ssize_t size;
3255a72c02bSZachary Turner   char *c;
3265a72c02bSZachary Turner   PyBytes_AsStringAndSize(m_py_obj, &c, &size);
3275a72c02bSZachary Turner   result->SetValue(std::string(c, size));
3285a72c02bSZachary Turner   return result;
3295a72c02bSZachary Turner }
3305a72c02bSZachary Turner 
331b9c1b51eSKate Stone PythonByteArray::PythonByteArray(llvm::ArrayRef<uint8_t> bytes)
332b9c1b51eSKate Stone     : PythonByteArray(bytes.data(), bytes.size()) {}
333f9d6d204SZachary Turner 
334b9c1b51eSKate Stone PythonByteArray::PythonByteArray(const uint8_t *bytes, size_t length) {
335f9d6d204SZachary Turner   const char *str = reinterpret_cast<const char *>(bytes);
336722b6189SLawrence D'Anna   *this = Take<PythonByteArray>(PyByteArray_FromStringAndSize(str, length));
337f9d6d204SZachary Turner }
338f9d6d204SZachary Turner 
339b9c1b51eSKate Stone bool PythonByteArray::Check(PyObject *py_obj) {
340f9d6d204SZachary Turner   if (!py_obj)
341f9d6d204SZachary Turner     return false;
342a6682a41SJonas Devlieghere   return PyByteArray_Check(py_obj);
343f9d6d204SZachary Turner }
344f9d6d204SZachary Turner 
345b9c1b51eSKate Stone llvm::ArrayRef<uint8_t> PythonByteArray::GetBytes() const {
346f9d6d204SZachary Turner   if (!IsValid())
347f9d6d204SZachary Turner     return llvm::ArrayRef<uint8_t>();
348f9d6d204SZachary Turner 
349f9d6d204SZachary Turner   char *c = PyByteArray_AsString(m_py_obj);
350f9d6d204SZachary Turner   size_t size = GetSize();
351f9d6d204SZachary Turner   return llvm::ArrayRef<uint8_t>(reinterpret_cast<uint8_t *>(c), size);
352f9d6d204SZachary Turner }
353f9d6d204SZachary Turner 
354b9c1b51eSKate Stone size_t PythonByteArray::GetSize() const {
355f9d6d204SZachary Turner   if (!IsValid())
356f9d6d204SZachary Turner     return 0;
357f9d6d204SZachary Turner 
358f9d6d204SZachary Turner   return PyByteArray_Size(m_py_obj);
359f9d6d204SZachary Turner }
360f9d6d204SZachary Turner 
361b9c1b51eSKate Stone StructuredData::StringSP PythonByteArray::CreateStructuredString() const {
362f9d6d204SZachary Turner   StructuredData::StringSP result(new StructuredData::String);
363f9d6d204SZachary Turner   llvm::ArrayRef<uint8_t> bytes = GetBytes();
364f9d6d204SZachary Turner   const char *str = reinterpret_cast<const char *>(bytes.data());
365f9d6d204SZachary Turner   result->SetValue(std::string(str, bytes.size()));
366f9d6d204SZachary Turner   return result;
367f9d6d204SZachary Turner }
368f9d6d204SZachary Turner 
3695a72c02bSZachary Turner // PythonString
3702c1f46dcSZachary Turner 
371085328eeSLawrence D'Anna Expected<PythonString> PythonString::FromUTF8(llvm::StringRef string) {
372085328eeSLawrence D'Anna #if PY_MAJOR_VERSION >= 3
373085328eeSLawrence D'Anna   PyObject *str = PyUnicode_FromStringAndSize(string.data(), string.size());
374085328eeSLawrence D'Anna #else
375085328eeSLawrence D'Anna   PyObject *str = PyString_FromStringAndSize(string.data(), string.size());
376085328eeSLawrence D'Anna #endif
377085328eeSLawrence D'Anna   if (!str)
378085328eeSLawrence D'Anna     return llvm::make_error<PythonException>();
379085328eeSLawrence D'Anna   return Take<PythonString>(str);
380085328eeSLawrence D'Anna }
381085328eeSLawrence D'Anna 
382d3bd5b3dSLawrence D'Anna PythonString::PythonString(llvm::StringRef string) { SetString(string); }
3832c1f46dcSZachary Turner 
384b9c1b51eSKate Stone bool PythonString::Check(PyObject *py_obj) {
38522c8efcdSZachary Turner   if (!py_obj)
38622c8efcdSZachary Turner     return false;
38718426935SZachary Turner 
3887d6d218eSZachary Turner   if (PyUnicode_Check(py_obj))
3897d6d218eSZachary Turner     return true;
3907d6d218eSZachary Turner #if PY_MAJOR_VERSION < 3
3917d6d218eSZachary Turner   if (PyString_Check(py_obj))
3927d6d218eSZachary Turner     return true;
39322c8efcdSZachary Turner #endif
3947d6d218eSZachary Turner   return false;
39522c8efcdSZachary Turner }
39622c8efcdSZachary Turner 
397d3bd5b3dSLawrence D'Anna void PythonString::Convert(PyRefType &type, PyObject *&py_obj) {
3987d6d218eSZachary Turner #if PY_MAJOR_VERSION < 3
3997d6d218eSZachary Turner   // In Python 2, Don't store PyUnicode objects directly, because we need
4007d6d218eSZachary Turner   // access to their underlying character buffers which Python 2 doesn't
4017d6d218eSZachary Turner   // provide.
402085328eeSLawrence D'Anna   if (PyUnicode_Check(py_obj)) {
403d3bd5b3dSLawrence D'Anna     PyObject *s = PyUnicode_AsUTF8String(py_obj);
404d3bd5b3dSLawrence D'Anna     if (s == nullptr) {
405085328eeSLawrence D'Anna       PyErr_Clear();
406d3bd5b3dSLawrence D'Anna       if (type == PyRefType::Owned)
407d3bd5b3dSLawrence D'Anna         Py_DECREF(py_obj);
408d3bd5b3dSLawrence D'Anna       return;
409d3bd5b3dSLawrence D'Anna     }
410d3bd5b3dSLawrence D'Anna     if (type == PyRefType::Owned)
411d3bd5b3dSLawrence D'Anna       Py_DECREF(py_obj);
412d3bd5b3dSLawrence D'Anna     else
413d3bd5b3dSLawrence D'Anna       type = PyRefType::Owned;
414d3bd5b3dSLawrence D'Anna     py_obj = s;
415085328eeSLawrence D'Anna   }
4167d6d218eSZachary Turner #endif
4172c1f46dcSZachary Turner }
4182c1f46dcSZachary Turner 
419b9c1b51eSKate Stone llvm::StringRef PythonString::GetString() const {
420085328eeSLawrence D'Anna   auto s = AsUTF8();
421085328eeSLawrence D'Anna   if (!s) {
422085328eeSLawrence D'Anna     llvm::consumeError(s.takeError());
423085328eeSLawrence D'Anna     return llvm::StringRef("");
424085328eeSLawrence D'Anna   }
425085328eeSLawrence D'Anna   return s.get();
426085328eeSLawrence D'Anna }
427085328eeSLawrence D'Anna 
428085328eeSLawrence D'Anna Expected<llvm::StringRef> PythonString::AsUTF8() const {
42918426935SZachary Turner   if (!IsValid())
430085328eeSLawrence D'Anna     return nullDeref();
43118426935SZachary Turner 
43222c8efcdSZachary Turner   Py_ssize_t size;
4335457b426SPavel Labath   const char *data;
43418426935SZachary Turner 
43518426935SZachary Turner #if PY_MAJOR_VERSION >= 3
4365457b426SPavel Labath   data = PyUnicode_AsUTF8AndSize(m_py_obj, &size);
43718426935SZachary Turner #else
438085328eeSLawrence D'Anna   char *c = NULL;
439085328eeSLawrence D'Anna   int r = PyString_AsStringAndSize(m_py_obj, &c, &size);
440085328eeSLawrence D'Anna   if (r < 0)
441085328eeSLawrence D'Anna     c = NULL;
4425457b426SPavel Labath   data = c;
44318426935SZachary Turner #endif
444085328eeSLawrence D'Anna 
445085328eeSLawrence D'Anna   if (!data)
446085328eeSLawrence D'Anna     return exception();
447085328eeSLawrence D'Anna 
4485457b426SPavel Labath   return llvm::StringRef(data, size);
44922c8efcdSZachary Turner }
4502c1f46dcSZachary Turner 
451b9c1b51eSKate Stone size_t PythonString::GetSize() const {
452b9c1b51eSKate Stone   if (IsValid()) {
45318426935SZachary Turner #if PY_MAJOR_VERSION >= 3
45418426935SZachary Turner     return PyUnicode_GetSize(m_py_obj);
45518426935SZachary Turner #else
45618426935SZachary Turner     return PyString_Size(m_py_obj);
45718426935SZachary Turner #endif
45818426935SZachary Turner   }
4592c1f46dcSZachary Turner   return 0;
4602c1f46dcSZachary Turner }
4612c1f46dcSZachary Turner 
462b9c1b51eSKate Stone void PythonString::SetString(llvm::StringRef string) {
463085328eeSLawrence D'Anna   auto s = FromUTF8(string);
464085328eeSLawrence D'Anna   if (!s) {
465085328eeSLawrence D'Anna     llvm::consumeError(s.takeError());
466085328eeSLawrence D'Anna     Reset();
467085328eeSLawrence D'Anna   } else {
46803819d1cSLawrence D'Anna     *this = std::move(s.get());
469085328eeSLawrence D'Anna   }
4702c1f46dcSZachary Turner }
4712c1f46dcSZachary Turner 
472b9c1b51eSKate Stone StructuredData::StringSP PythonString::CreateStructuredString() const {
4732c1f46dcSZachary Turner   StructuredData::StringSP result(new StructuredData::String);
4742c1f46dcSZachary Turner   result->SetValue(GetString());
4752c1f46dcSZachary Turner   return result;
4762c1f46dcSZachary Turner }
4772c1f46dcSZachary Turner 
4782c1f46dcSZachary Turner // PythonInteger
4792c1f46dcSZachary Turner 
480d3bd5b3dSLawrence D'Anna PythonInteger::PythonInteger(int64_t value) { SetInteger(value); }
4812c1f46dcSZachary Turner 
482b9c1b51eSKate Stone bool PythonInteger::Check(PyObject *py_obj) {
48322c8efcdSZachary Turner   if (!py_obj)
48422c8efcdSZachary Turner     return false;
48522c8efcdSZachary Turner 
48622c8efcdSZachary Turner #if PY_MAJOR_VERSION >= 3
48705097246SAdrian Prantl   // Python 3 does not have PyInt_Check.  There is only one type of integral
48805097246SAdrian Prantl   // value, long.
48922c8efcdSZachary Turner   return PyLong_Check(py_obj);
49022c8efcdSZachary Turner #else
49122c8efcdSZachary Turner   return PyLong_Check(py_obj) || PyInt_Check(py_obj);
49222c8efcdSZachary Turner #endif
4932c1f46dcSZachary Turner }
4942c1f46dcSZachary Turner 
495d3bd5b3dSLawrence D'Anna void PythonInteger::Convert(PyRefType &type, PyObject *&py_obj) {
49622c8efcdSZachary Turner #if PY_MAJOR_VERSION < 3
49705097246SAdrian Prantl   // Always store this as a PyLong, which makes interoperability between Python
49805097246SAdrian Prantl   // 2.x and Python 3.x easier.  This is only necessary in 2.x, since 3.x
49905097246SAdrian Prantl   // doesn't even have a PyInt.
500b9c1b51eSKate Stone   if (PyInt_Check(py_obj)) {
501f8b22f8fSZachary Turner     // Since we converted the original object to a different type, the new
50205097246SAdrian Prantl     // object is an owned object regardless of the ownership semantics
50305097246SAdrian Prantl     // requested by the user.
504d3bd5b3dSLawrence D'Anna     long long value = PyInt_AsLong(py_obj);
505d3bd5b3dSLawrence D'Anna     PyObject *l = nullptr;
506d3bd5b3dSLawrence D'Anna     if (!PyErr_Occurred())
507d3bd5b3dSLawrence D'Anna       l = PyLong_FromLongLong(value);
508d3bd5b3dSLawrence D'Anna     if (l == nullptr) {
509d3bd5b3dSLawrence D'Anna       PyErr_Clear();
510d3bd5b3dSLawrence D'Anna       if (type == PyRefType::Owned)
511d3bd5b3dSLawrence D'Anna         Py_DECREF(py_obj);
512d3bd5b3dSLawrence D'Anna       return;
513d3bd5b3dSLawrence D'Anna     }
514d3bd5b3dSLawrence D'Anna     if (type == PyRefType::Owned)
515d3bd5b3dSLawrence D'Anna       Py_DECREF(py_obj);
516d3bd5b3dSLawrence D'Anna     else
517d3bd5b3dSLawrence D'Anna       type = PyRefType::Owned;
518d3bd5b3dSLawrence D'Anna     py_obj = l;
51922c8efcdSZachary Turner   }
52022c8efcdSZachary Turner #endif
5212c1f46dcSZachary Turner }
5222c1f46dcSZachary Turner 
523b9c1b51eSKate Stone void PythonInteger::SetInteger(int64_t value) {
52404edd189SLawrence D'Anna   *this = Take<PythonInteger>(PyLong_FromLongLong(value));
5252c1f46dcSZachary Turner }
5262c1f46dcSZachary Turner 
527b9c1b51eSKate Stone StructuredData::IntegerSP PythonInteger::CreateStructuredInteger() const {
5282c1f46dcSZachary Turner   StructuredData::IntegerSP result(new StructuredData::Integer);
529*52712d3fSLawrence D'Anna   // FIXME this is really not ideal.   Errors are silently converted to 0
530*52712d3fSLawrence D'Anna   // and overflows are silently wrapped.   But we'd need larger changes
531*52712d3fSLawrence D'Anna   // to StructuredData to fix it, so that's how it is for now.
532*52712d3fSLawrence D'Anna   llvm::Expected<unsigned long long> value = AsModuloUnsignedLongLong();
533*52712d3fSLawrence D'Anna   if (!value) {
534*52712d3fSLawrence D'Anna     llvm::consumeError(value.takeError());
535*52712d3fSLawrence D'Anna     result->SetValue(0);
536*52712d3fSLawrence D'Anna   } else {
537*52712d3fSLawrence D'Anna     result->SetValue(value.get());
538*52712d3fSLawrence D'Anna   }
5392c1f46dcSZachary Turner   return result;
5402c1f46dcSZachary Turner }
5412c1f46dcSZachary Turner 
542b81d715cSTatyana Krasnukha // PythonBoolean
543b81d715cSTatyana Krasnukha 
544b81d715cSTatyana Krasnukha PythonBoolean::PythonBoolean(bool value) {
545b81d715cSTatyana Krasnukha   SetValue(value);
546b81d715cSTatyana Krasnukha }
547b81d715cSTatyana Krasnukha 
548b81d715cSTatyana Krasnukha bool PythonBoolean::Check(PyObject *py_obj) {
549b81d715cSTatyana Krasnukha   return py_obj ? PyBool_Check(py_obj) : false;
550b81d715cSTatyana Krasnukha }
551b81d715cSTatyana Krasnukha 
552b81d715cSTatyana Krasnukha bool PythonBoolean::GetValue() const {
553b81d715cSTatyana Krasnukha   return m_py_obj ? PyObject_IsTrue(m_py_obj) : false;
554b81d715cSTatyana Krasnukha }
555b81d715cSTatyana Krasnukha 
556b81d715cSTatyana Krasnukha void PythonBoolean::SetValue(bool value) {
55704edd189SLawrence D'Anna   *this = Take<PythonBoolean>(PyBool_FromLong(value));
558b81d715cSTatyana Krasnukha }
559b81d715cSTatyana Krasnukha 
560b81d715cSTatyana Krasnukha StructuredData::BooleanSP PythonBoolean::CreateStructuredBoolean() const {
561b81d715cSTatyana Krasnukha   StructuredData::BooleanSP result(new StructuredData::Boolean);
562b81d715cSTatyana Krasnukha   result->SetValue(GetValue());
563b81d715cSTatyana Krasnukha   return result;
564b81d715cSTatyana Krasnukha }
565b81d715cSTatyana Krasnukha 
5662c1f46dcSZachary Turner // PythonList
5672c1f46dcSZachary Turner 
568d3bd5b3dSLawrence D'Anna PythonList::PythonList(PyInitialValue value) {
569f8b22f8fSZachary Turner   if (value == PyInitialValue::Empty)
570722b6189SLawrence D'Anna     *this = Take<PythonList>(PyList_New(0));
5712c1f46dcSZachary Turner }
5722c1f46dcSZachary Turner 
573d3bd5b3dSLawrence D'Anna PythonList::PythonList(int list_size) {
574722b6189SLawrence D'Anna   *this = Take<PythonList>(PyList_New(list_size));
57587f47729SZachary Turner }
57687f47729SZachary Turner 
577b9c1b51eSKate Stone bool PythonList::Check(PyObject *py_obj) {
57822c8efcdSZachary Turner   if (!py_obj)
57922c8efcdSZachary Turner     return false;
58022c8efcdSZachary Turner   return PyList_Check(py_obj);
58122c8efcdSZachary Turner }
58222c8efcdSZachary Turner 
583b9c1b51eSKate Stone uint32_t PythonList::GetSize() const {
584f8b22f8fSZachary Turner   if (IsValid())
5852c1f46dcSZachary Turner     return PyList_GET_SIZE(m_py_obj);
5862c1f46dcSZachary Turner   return 0;
5872c1f46dcSZachary Turner }
5882c1f46dcSZachary Turner 
589b9c1b51eSKate Stone PythonObject PythonList::GetItemAtIndex(uint32_t index) const {
590f8b22f8fSZachary Turner   if (IsValid())
591f8b22f8fSZachary Turner     return PythonObject(PyRefType::Borrowed, PyList_GetItem(m_py_obj, index));
5922c1f46dcSZachary Turner   return PythonObject();
5932c1f46dcSZachary Turner }
5942c1f46dcSZachary Turner 
595b9c1b51eSKate Stone void PythonList::SetItemAtIndex(uint32_t index, const PythonObject &object) {
596b9c1b51eSKate Stone   if (IsAllocated() && object.IsValid()) {
597f8b22f8fSZachary Turner     // PyList_SetItem is documented to "steal" a reference, so we need to
598f8b22f8fSZachary Turner     // convert it to an owned reference by incrementing it.
599f8b22f8fSZachary Turner     Py_INCREF(object.get());
6002c1f46dcSZachary Turner     PyList_SetItem(m_py_obj, index, object.get());
6012c1f46dcSZachary Turner   }
602f8b22f8fSZachary Turner }
6032c1f46dcSZachary Turner 
604b9c1b51eSKate Stone void PythonList::AppendItem(const PythonObject &object) {
605b9c1b51eSKate Stone   if (IsAllocated() && object.IsValid()) {
606f8b22f8fSZachary Turner     // `PyList_Append` does *not* steal a reference, so do not call `Py_INCREF`
607f8b22f8fSZachary Turner     // here like we do with `PyList_SetItem`.
6082c1f46dcSZachary Turner     PyList_Append(m_py_obj, object.get());
6092c1f46dcSZachary Turner   }
610f8b22f8fSZachary Turner }
6112c1f46dcSZachary Turner 
612b9c1b51eSKate Stone StructuredData::ArraySP PythonList::CreateStructuredArray() const {
6132c1f46dcSZachary Turner   StructuredData::ArraySP result(new StructuredData::Array);
6142c1f46dcSZachary Turner   uint32_t count = GetSize();
615b9c1b51eSKate Stone   for (uint32_t i = 0; i < count; ++i) {
6162c1f46dcSZachary Turner     PythonObject obj = GetItemAtIndex(i);
6172c1f46dcSZachary Turner     result->AddItem(obj.CreateStructuredObject());
6182c1f46dcSZachary Turner   }
6192c1f46dcSZachary Turner   return result;
6202c1f46dcSZachary Turner }
6212c1f46dcSZachary Turner 
622a1405147SZachary Turner // PythonTuple
623a1405147SZachary Turner 
624d3bd5b3dSLawrence D'Anna PythonTuple::PythonTuple(PyInitialValue value) {
625a1405147SZachary Turner   if (value == PyInitialValue::Empty)
626722b6189SLawrence D'Anna     *this = Take<PythonTuple>(PyTuple_New(0));
627a1405147SZachary Turner }
628a1405147SZachary Turner 
629d3bd5b3dSLawrence D'Anna PythonTuple::PythonTuple(int tuple_size) {
630722b6189SLawrence D'Anna   *this = Take<PythonTuple>(PyTuple_New(tuple_size));
631a1405147SZachary Turner }
632a1405147SZachary Turner 
633b9c1b51eSKate Stone PythonTuple::PythonTuple(std::initializer_list<PythonObject> objects) {
634a1405147SZachary Turner   m_py_obj = PyTuple_New(objects.size());
635a1405147SZachary Turner 
636a1405147SZachary Turner   uint32_t idx = 0;
637b9c1b51eSKate Stone   for (auto object : objects) {
638a1405147SZachary Turner     if (object.IsValid())
639a1405147SZachary Turner       SetItemAtIndex(idx, object);
640a1405147SZachary Turner     idx++;
641a1405147SZachary Turner   }
642a1405147SZachary Turner }
643a1405147SZachary Turner 
644b9c1b51eSKate Stone PythonTuple::PythonTuple(std::initializer_list<PyObject *> objects) {
645a1405147SZachary Turner   m_py_obj = PyTuple_New(objects.size());
646a1405147SZachary Turner 
647a1405147SZachary Turner   uint32_t idx = 0;
648b9c1b51eSKate Stone   for (auto py_object : objects) {
649a1405147SZachary Turner     PythonObject object(PyRefType::Borrowed, py_object);
650a1405147SZachary Turner     if (object.IsValid())
651a1405147SZachary Turner       SetItemAtIndex(idx, object);
652a1405147SZachary Turner     idx++;
653a1405147SZachary Turner   }
654a1405147SZachary Turner }
655a1405147SZachary Turner 
656b9c1b51eSKate Stone bool PythonTuple::Check(PyObject *py_obj) {
657a1405147SZachary Turner   if (!py_obj)
658a1405147SZachary Turner     return false;
659a1405147SZachary Turner   return PyTuple_Check(py_obj);
660a1405147SZachary Turner }
661a1405147SZachary Turner 
662b9c1b51eSKate Stone uint32_t PythonTuple::GetSize() const {
663a1405147SZachary Turner   if (IsValid())
664a1405147SZachary Turner     return PyTuple_GET_SIZE(m_py_obj);
665a1405147SZachary Turner   return 0;
666a1405147SZachary Turner }
667a1405147SZachary Turner 
668b9c1b51eSKate Stone PythonObject PythonTuple::GetItemAtIndex(uint32_t index) const {
669a1405147SZachary Turner   if (IsValid())
670a1405147SZachary Turner     return PythonObject(PyRefType::Borrowed, PyTuple_GetItem(m_py_obj, index));
671a1405147SZachary Turner   return PythonObject();
672a1405147SZachary Turner }
673a1405147SZachary Turner 
674b9c1b51eSKate Stone void PythonTuple::SetItemAtIndex(uint32_t index, const PythonObject &object) {
675b9c1b51eSKate Stone   if (IsAllocated() && object.IsValid()) {
676a1405147SZachary Turner     // PyTuple_SetItem is documented to "steal" a reference, so we need to
677a1405147SZachary Turner     // convert it to an owned reference by incrementing it.
678a1405147SZachary Turner     Py_INCREF(object.get());
679a1405147SZachary Turner     PyTuple_SetItem(m_py_obj, index, object.get());
680a1405147SZachary Turner   }
681a1405147SZachary Turner }
682a1405147SZachary Turner 
683b9c1b51eSKate Stone StructuredData::ArraySP PythonTuple::CreateStructuredArray() const {
684a1405147SZachary Turner   StructuredData::ArraySP result(new StructuredData::Array);
685a1405147SZachary Turner   uint32_t count = GetSize();
686b9c1b51eSKate Stone   for (uint32_t i = 0; i < count; ++i) {
687a1405147SZachary Turner     PythonObject obj = GetItemAtIndex(i);
688a1405147SZachary Turner     result->AddItem(obj.CreateStructuredObject());
689a1405147SZachary Turner   }
690a1405147SZachary Turner   return result;
691a1405147SZachary Turner }
692a1405147SZachary Turner 
6932c1f46dcSZachary Turner // PythonDictionary
6942c1f46dcSZachary Turner 
695d3bd5b3dSLawrence D'Anna PythonDictionary::PythonDictionary(PyInitialValue value) {
696f8b22f8fSZachary Turner   if (value == PyInitialValue::Empty)
697722b6189SLawrence D'Anna     *this = Take<PythonDictionary>(PyDict_New());
6982c1f46dcSZachary Turner }
6992c1f46dcSZachary Turner 
700b9c1b51eSKate Stone bool PythonDictionary::Check(PyObject *py_obj) {
70122c8efcdSZachary Turner   if (!py_obj)
70222c8efcdSZachary Turner     return false;
70322c8efcdSZachary Turner 
70422c8efcdSZachary Turner   return PyDict_Check(py_obj);
70522c8efcdSZachary Turner }
70622c8efcdSZachary Turner 
707b9c1b51eSKate Stone uint32_t PythonDictionary::GetSize() const {
708f8b22f8fSZachary Turner   if (IsValid())
7092c1f46dcSZachary Turner     return PyDict_Size(m_py_obj);
7102c1f46dcSZachary Turner   return 0;
7112c1f46dcSZachary Turner }
7122c1f46dcSZachary Turner 
713b9c1b51eSKate Stone PythonList PythonDictionary::GetKeys() const {
714f8b22f8fSZachary Turner   if (IsValid())
715f8b22f8fSZachary Turner     return PythonList(PyRefType::Owned, PyDict_Keys(m_py_obj));
716f8b22f8fSZachary Turner   return PythonList(PyInitialValue::Invalid);
7172c1f46dcSZachary Turner }
7182c1f46dcSZachary Turner 
719b9c1b51eSKate Stone PythonObject PythonDictionary::GetItemForKey(const PythonObject &key) const {
720c86a6acaSLawrence D'Anna   auto item = GetItem(key);
721c86a6acaSLawrence D'Anna   if (!item) {
722c86a6acaSLawrence D'Anna     llvm::consumeError(item.takeError());
7232c1f46dcSZachary Turner     return PythonObject();
7242c1f46dcSZachary Turner   }
725c86a6acaSLawrence D'Anna   return std::move(item.get());
726c86a6acaSLawrence D'Anna }
727c86a6acaSLawrence D'Anna 
728c86a6acaSLawrence D'Anna Expected<PythonObject>
729c86a6acaSLawrence D'Anna PythonDictionary::GetItem(const PythonObject &key) const {
730c86a6acaSLawrence D'Anna   if (!IsValid())
731c86a6acaSLawrence D'Anna     return nullDeref();
732c86a6acaSLawrence D'Anna #if PY_MAJOR_VERSION >= 3
733c86a6acaSLawrence D'Anna   PyObject *o = PyDict_GetItemWithError(m_py_obj, key.get());
734c86a6acaSLawrence D'Anna   if (PyErr_Occurred())
735c86a6acaSLawrence D'Anna     return exception();
736c86a6acaSLawrence D'Anna #else
737c86a6acaSLawrence D'Anna   PyObject *o = PyDict_GetItem(m_py_obj, key.get());
738c86a6acaSLawrence D'Anna #endif
739c86a6acaSLawrence D'Anna   if (!o)
740c86a6acaSLawrence D'Anna     return keyError();
741c86a6acaSLawrence D'Anna   return Retain<PythonObject>(o);
742c86a6acaSLawrence D'Anna }
743c86a6acaSLawrence D'Anna 
744722b6189SLawrence D'Anna Expected<PythonObject> PythonDictionary::GetItem(const Twine &key) const {
745c86a6acaSLawrence D'Anna   if (!IsValid())
746c86a6acaSLawrence D'Anna     return nullDeref();
747722b6189SLawrence D'Anna   PyObject *o = PyDict_GetItemString(m_py_obj, NullTerminated(key));
748c86a6acaSLawrence D'Anna   if (PyErr_Occurred())
749c86a6acaSLawrence D'Anna     return exception();
750c86a6acaSLawrence D'Anna   if (!o)
751c86a6acaSLawrence D'Anna     return keyError();
752c86a6acaSLawrence D'Anna   return Retain<PythonObject>(o);
753c86a6acaSLawrence D'Anna }
754c86a6acaSLawrence D'Anna 
755c86a6acaSLawrence D'Anna Error PythonDictionary::SetItem(const PythonObject &key,
756c86a6acaSLawrence D'Anna                                 const PythonObject &value) const {
757c86a6acaSLawrence D'Anna   if (!IsValid() || !value.IsValid())
758c86a6acaSLawrence D'Anna     return nullDeref();
759c86a6acaSLawrence D'Anna   int r = PyDict_SetItem(m_py_obj, key.get(), value.get());
760c86a6acaSLawrence D'Anna   if (r < 0)
761c86a6acaSLawrence D'Anna     return exception();
762c86a6acaSLawrence D'Anna   return Error::success();
763c86a6acaSLawrence D'Anna }
764c86a6acaSLawrence D'Anna 
765722b6189SLawrence D'Anna Error PythonDictionary::SetItem(const Twine &key,
766c86a6acaSLawrence D'Anna                                 const PythonObject &value) const {
767c86a6acaSLawrence D'Anna   if (!IsValid() || !value.IsValid())
768c86a6acaSLawrence D'Anna     return nullDeref();
769722b6189SLawrence D'Anna   int r = PyDict_SetItemString(m_py_obj, NullTerminated(key), value.get());
770c86a6acaSLawrence D'Anna   if (r < 0)
771c86a6acaSLawrence D'Anna     return exception();
772c86a6acaSLawrence D'Anna   return Error::success();
773c86a6acaSLawrence D'Anna }
7742c1f46dcSZachary Turner 
775b9c1b51eSKate Stone void PythonDictionary::SetItemForKey(const PythonObject &key,
776b9c1b51eSKate Stone                                      const PythonObject &value) {
777c86a6acaSLawrence D'Anna   Error error = SetItem(key, value);
778c86a6acaSLawrence D'Anna   if (error)
779c86a6acaSLawrence D'Anna     llvm::consumeError(std::move(error));
7802c1f46dcSZachary Turner }
7812c1f46dcSZachary Turner 
7822c1f46dcSZachary Turner StructuredData::DictionarySP
783b9c1b51eSKate Stone PythonDictionary::CreateStructuredDictionary() const {
7842c1f46dcSZachary Turner   StructuredData::DictionarySP result(new StructuredData::Dictionary);
7852c1f46dcSZachary Turner   PythonList keys(GetKeys());
7862c1f46dcSZachary Turner   uint32_t num_keys = keys.GetSize();
787b9c1b51eSKate Stone   for (uint32_t i = 0; i < num_keys; ++i) {
7882c1f46dcSZachary Turner     PythonObject key = keys.GetItemAtIndex(i);
7892c1f46dcSZachary Turner     PythonObject value = GetItemForKey(key);
7902c1f46dcSZachary Turner     StructuredData::ObjectSP structured_value = value.CreateStructuredObject();
791f8b22f8fSZachary Turner     result->AddItem(key.Str().GetString(), structured_value);
7922c1f46dcSZachary Turner   }
7932c1f46dcSZachary Turner   return result;
7942c1f46dcSZachary Turner }
7952c1f46dcSZachary Turner 
796b9c1b51eSKate Stone PythonModule PythonModule::BuiltinsModule() {
797a1405147SZachary Turner #if PY_MAJOR_VERSION >= 3
798a1405147SZachary Turner   return AddModule("builtins");
799a1405147SZachary Turner #else
800a1405147SZachary Turner   return AddModule("__builtin__");
801a1405147SZachary Turner #endif
802a1405147SZachary Turner }
803a1405147SZachary Turner 
804b9c1b51eSKate Stone PythonModule PythonModule::MainModule() { return AddModule("__main__"); }
805a1405147SZachary Turner 
806b9c1b51eSKate Stone PythonModule PythonModule::AddModule(llvm::StringRef module) {
807a1405147SZachary Turner   std::string str = module.str();
808a1405147SZachary Turner   return PythonModule(PyRefType::Borrowed, PyImport_AddModule(str.c_str()));
8097841efbbSZachary Turner }
8107841efbbSZachary Turner 
811722b6189SLawrence D'Anna Expected<PythonModule> PythonModule::Import(const Twine &name) {
812722b6189SLawrence D'Anna   PyObject *mod = PyImport_ImportModule(NullTerminated(name));
813085328eeSLawrence D'Anna   if (!mod)
814085328eeSLawrence D'Anna     return exception();
815085328eeSLawrence D'Anna   return Take<PythonModule>(mod);
816085328eeSLawrence D'Anna }
817085328eeSLawrence D'Anna 
818722b6189SLawrence D'Anna Expected<PythonObject> PythonModule::Get(const Twine &name) {
819085328eeSLawrence D'Anna   if (!IsValid())
820085328eeSLawrence D'Anna     return nullDeref();
821085328eeSLawrence D'Anna   PyObject *dict = PyModule_GetDict(m_py_obj);
822085328eeSLawrence D'Anna   if (!dict)
823085328eeSLawrence D'Anna     return exception();
824722b6189SLawrence D'Anna   PyObject *item = PyDict_GetItemString(dict, NullTerminated(name));
825085328eeSLawrence D'Anna   if (!item)
826085328eeSLawrence D'Anna     return exception();
827085328eeSLawrence D'Anna   return Retain<PythonObject>(item);
8282419f1d5SZachary Turner }
8292419f1d5SZachary Turner 
830b9c1b51eSKate Stone bool PythonModule::Check(PyObject *py_obj) {
8317841efbbSZachary Turner   if (!py_obj)
8327841efbbSZachary Turner     return false;
8337841efbbSZachary Turner 
8347841efbbSZachary Turner   return PyModule_Check(py_obj);
8357841efbbSZachary Turner }
8367841efbbSZachary Turner 
837b9c1b51eSKate Stone PythonDictionary PythonModule::GetDictionary() const {
838722b6189SLawrence D'Anna   if (!IsValid())
839722b6189SLawrence D'Anna     return PythonDictionary();
840722b6189SLawrence D'Anna   return Retain<PythonDictionary>(PyModule_GetDict(m_py_obj));
8417841efbbSZachary Turner }
8427841efbbSZachary Turner 
843b9c1b51eSKate Stone bool PythonCallable::Check(PyObject *py_obj) {
844a1405147SZachary Turner   if (!py_obj)
845a1405147SZachary Turner     return false;
846a1405147SZachary Turner 
847a1405147SZachary Turner   return PyCallable_Check(py_obj);
848a1405147SZachary Turner }
849a1405147SZachary Turner 
850c86a6acaSLawrence D'Anna #if PY_MAJOR_VERSION >= 3 && PY_MINOR_VERSION >= 3
851c86a6acaSLawrence D'Anna static const char get_arg_info_script[] = R"(
852c86a6acaSLawrence D'Anna from inspect import signature, Parameter, ismethod
853c86a6acaSLawrence D'Anna from collections import namedtuple
854adbf64ccSLawrence D'Anna ArgInfo = namedtuple('ArgInfo', ['count', 'has_varargs'])
85504edd189SLawrence D'Anna def main(f):
856c86a6acaSLawrence D'Anna     count = 0
857c86a6acaSLawrence D'Anna     varargs = False
858c86a6acaSLawrence D'Anna     for parameter in signature(f).parameters.values():
859c86a6acaSLawrence D'Anna         kind = parameter.kind
860c86a6acaSLawrence D'Anna         if kind in (Parameter.POSITIONAL_ONLY,
861c86a6acaSLawrence D'Anna                     Parameter.POSITIONAL_OR_KEYWORD):
862c86a6acaSLawrence D'Anna             count += 1
863c86a6acaSLawrence D'Anna         elif kind == Parameter.VAR_POSITIONAL:
864c86a6acaSLawrence D'Anna             varargs = True
865c86a6acaSLawrence D'Anna         elif kind in (Parameter.KEYWORD_ONLY,
866c86a6acaSLawrence D'Anna                       Parameter.VAR_KEYWORD):
867c86a6acaSLawrence D'Anna             pass
868c86a6acaSLawrence D'Anna         else:
869c86a6acaSLawrence D'Anna             raise Exception(f'unknown parameter kind: {kind}')
870adbf64ccSLawrence D'Anna     return ArgInfo(count, varargs)
871c86a6acaSLawrence D'Anna )";
872c86a6acaSLawrence D'Anna #endif
873c86a6acaSLawrence D'Anna 
874c86a6acaSLawrence D'Anna Expected<PythonCallable::ArgInfo> PythonCallable::GetArgInfo() const {
875c86a6acaSLawrence D'Anna   ArgInfo result = {};
876c86a6acaSLawrence D'Anna   if (!IsValid())
877c86a6acaSLawrence D'Anna     return nullDeref();
878c86a6acaSLawrence D'Anna 
879c86a6acaSLawrence D'Anna #if PY_MAJOR_VERSION >= 3 && PY_MINOR_VERSION >= 3
880c86a6acaSLawrence D'Anna 
88104edd189SLawrence D'Anna   // no need to synchronize access to this global, we already have the GIL
88204edd189SLawrence D'Anna   static PythonScript get_arg_info(get_arg_info_script);
88304edd189SLawrence D'Anna   Expected<PythonObject> pyarginfo = get_arg_info(*this);
884c86a6acaSLawrence D'Anna   if (!pyarginfo)
885c86a6acaSLawrence D'Anna     return pyarginfo.takeError();
886adbf64ccSLawrence D'Anna   long long count =
887adbf64ccSLawrence D'Anna       cantFail(As<long long>(pyarginfo.get().GetAttribute("count")));
888adbf64ccSLawrence D'Anna   bool has_varargs =
889c86a6acaSLawrence D'Anna       cantFail(As<bool>(pyarginfo.get().GetAttribute("has_varargs")));
890adbf64ccSLawrence D'Anna   result.max_positional_args = has_varargs ? ArgInfo::UNBOUNDED : count;
891c86a6acaSLawrence D'Anna 
892c86a6acaSLawrence D'Anna #else
893adbf64ccSLawrence D'Anna   PyObject *py_func_obj;
8942386537cSLawrence D'Anna   bool is_bound_method = false;
895adbf64ccSLawrence D'Anna   bool is_class = false;
896adbf64ccSLawrence D'Anna 
897adbf64ccSLawrence D'Anna   if (PyType_Check(m_py_obj) || PyClass_Check(m_py_obj)) {
898adbf64ccSLawrence D'Anna     auto init = GetAttribute("__init__");
899adbf64ccSLawrence D'Anna     if (!init)
900adbf64ccSLawrence D'Anna       return init.takeError();
901adbf64ccSLawrence D'Anna     py_func_obj = init.get().get();
902adbf64ccSLawrence D'Anna     is_class = true;
903adbf64ccSLawrence D'Anna   } else {
904adbf64ccSLawrence D'Anna     py_func_obj = m_py_obj;
905adbf64ccSLawrence D'Anna   }
906adbf64ccSLawrence D'Anna 
907b9c1b51eSKate Stone   if (PyMethod_Check(py_func_obj)) {
908a1405147SZachary Turner     py_func_obj = PyMethod_GET_FUNCTION(py_func_obj);
909a5d6765cSEnrico Granata     PythonObject im_self = GetAttributeValue("im_self");
910a5d6765cSEnrico Granata     if (im_self.IsValid() && !im_self.IsNone())
9112386537cSLawrence D'Anna       is_bound_method = true;
912b9c1b51eSKate Stone   } else {
913a5d6765cSEnrico Granata     // see if this is a callable object with an __call__ method
914b9c1b51eSKate Stone     if (!PyFunction_Check(py_func_obj)) {
915a5d6765cSEnrico Granata       PythonObject __call__ = GetAttributeValue("__call__");
916b9c1b51eSKate Stone       if (__call__.IsValid()) {
917a5d6765cSEnrico Granata         auto __callable__ = __call__.AsType<PythonCallable>();
918b9c1b51eSKate Stone         if (__callable__.IsValid()) {
919a5d6765cSEnrico Granata           py_func_obj = PyMethod_GET_FUNCTION(__callable__.get());
9202386537cSLawrence D'Anna           PythonObject im_self = __callable__.GetAttributeValue("im_self");
921a5d6765cSEnrico Granata           if (im_self.IsValid() && !im_self.IsNone())
9222386537cSLawrence D'Anna             is_bound_method = true;
923a5d6765cSEnrico Granata         }
924a5d6765cSEnrico Granata       }
925a5d6765cSEnrico Granata     }
926a5d6765cSEnrico Granata   }
927a1405147SZachary Turner 
928a1405147SZachary Turner   if (!py_func_obj)
929b58fb2f4SZachary Turner     return result;
930a1405147SZachary Turner 
931a1405147SZachary Turner   PyCodeObject *code = (PyCodeObject *)PyFunction_GET_CODE(py_func_obj);
932a1405147SZachary Turner   if (!code)
933b58fb2f4SZachary Turner     return result;
934a1405147SZachary Turner 
935adbf64ccSLawrence D'Anna   auto count = code->co_argcount;
936adbf64ccSLawrence D'Anna   bool has_varargs = !!(code->co_flags & CO_VARARGS);
937adbf64ccSLawrence D'Anna   result.max_positional_args =
938adbf64ccSLawrence D'Anna       has_varargs ? ArgInfo::UNBOUNDED
939adbf64ccSLawrence D'Anna                   : (count - (int)is_bound_method) - (int)is_class;
940c86a6acaSLawrence D'Anna 
941c86a6acaSLawrence D'Anna #endif
942c86a6acaSLawrence D'Anna 
943b58fb2f4SZachary Turner   return result;
944b58fb2f4SZachary Turner }
945b58fb2f4SZachary Turner 
9462386537cSLawrence D'Anna constexpr unsigned
9472386537cSLawrence D'Anna     PythonCallable::ArgInfo::UNBOUNDED; // FIXME delete after c++17
9482386537cSLawrence D'Anna 
949b9c1b51eSKate Stone PythonObject PythonCallable::operator()() {
950b9c1b51eSKate Stone   return PythonObject(PyRefType::Owned, PyObject_CallObject(m_py_obj, nullptr));
951a1405147SZachary Turner }
952a1405147SZachary Turner 
953b9c1b51eSKate Stone PythonObject PythonCallable::
954b9c1b51eSKate Stone operator()(std::initializer_list<PyObject *> args) {
955a1405147SZachary Turner   PythonTuple arg_tuple(args);
956a1405147SZachary Turner   return PythonObject(PyRefType::Owned,
957a1405147SZachary Turner                       PyObject_CallObject(m_py_obj, arg_tuple.get()));
958a1405147SZachary Turner }
959a1405147SZachary Turner 
960b9c1b51eSKate Stone PythonObject PythonCallable::
961b9c1b51eSKate Stone operator()(std::initializer_list<PythonObject> args) {
962a1405147SZachary Turner   PythonTuple arg_tuple(args);
963a1405147SZachary Turner   return PythonObject(PyRefType::Owned,
964a1405147SZachary Turner                       PyObject_CallObject(m_py_obj, arg_tuple.get()));
965a1405147SZachary Turner }
966a1405147SZachary Turner 
967b9c1b51eSKate Stone bool PythonFile::Check(PyObject *py_obj) {
96896898eb6SLawrence D'Anna   if (!py_obj)
96996898eb6SLawrence D'Anna     return false;
9709c40264fSZachary Turner #if PY_MAJOR_VERSION < 3
97123502721SJason Molenda   return PyFile_Check(py_obj);
97223502721SJason Molenda #else
9739c40264fSZachary Turner   // In Python 3, there is no `PyFile_Check`, and in fact PyFile is not even a
9749c40264fSZachary Turner   // first-class object type anymore.  `PyFile_FromFd` is just a thin wrapper
97505097246SAdrian Prantl   // over `io.open()`, which returns some object derived from `io.IOBase`. As a
97605097246SAdrian Prantl   // result, the only way to detect a file in Python 3 is to check whether it
97721b8a8aeSLawrence D'Anna   // inherits from `io.IOBase`.
97821b8a8aeSLawrence D'Anna   auto io_module = PythonModule::Import("io");
97921b8a8aeSLawrence D'Anna   if (!io_module) {
98021b8a8aeSLawrence D'Anna     llvm::consumeError(io_module.takeError());
9819c40264fSZachary Turner     return false;
98221b8a8aeSLawrence D'Anna   }
98321b8a8aeSLawrence D'Anna   auto iobase = io_module.get().Get("IOBase");
98421b8a8aeSLawrence D'Anna   if (!iobase) {
98521b8a8aeSLawrence D'Anna     llvm::consumeError(iobase.takeError());
9869c40264fSZachary Turner     return false;
98721b8a8aeSLawrence D'Anna   }
98821b8a8aeSLawrence D'Anna   int r = PyObject_IsInstance(py_obj, iobase.get().get());
98921b8a8aeSLawrence D'Anna   if (r < 0) {
99021b8a8aeSLawrence D'Anna     llvm::consumeError(exception()); // clear the exception and log it.
99121b8a8aeSLawrence D'Anna     return false;
99221b8a8aeSLawrence D'Anna   }
99321b8a8aeSLawrence D'Anna   return !!r;
99423502721SJason Molenda #endif
9959c40264fSZachary Turner }
9969c40264fSZachary Turner 
99721b8a8aeSLawrence D'Anna namespace {
99821b8a8aeSLawrence D'Anna class GIL {
99921b8a8aeSLawrence D'Anna public:
100021b8a8aeSLawrence D'Anna   GIL() {
100121b8a8aeSLawrence D'Anna     m_state = PyGILState_Ensure();
100221b8a8aeSLawrence D'Anna     assert(!PyErr_Occurred());
100321b8a8aeSLawrence D'Anna   }
100421b8a8aeSLawrence D'Anna   ~GIL() { PyGILState_Release(m_state); }
100521b8a8aeSLawrence D'Anna 
100621b8a8aeSLawrence D'Anna protected:
100721b8a8aeSLawrence D'Anna   PyGILState_STATE m_state;
100821b8a8aeSLawrence D'Anna };
100921b8a8aeSLawrence D'Anna } // namespace
101021b8a8aeSLawrence D'Anna 
1011085328eeSLawrence D'Anna const char *PythonException::toCString() const {
1012085328eeSLawrence D'Anna   if (!m_repr_bytes)
1013085328eeSLawrence D'Anna     return "unknown exception";
1014085328eeSLawrence D'Anna   return PyBytes_AS_STRING(m_repr_bytes);
1015085328eeSLawrence D'Anna }
1016085328eeSLawrence D'Anna 
1017085328eeSLawrence D'Anna PythonException::PythonException(const char *caller) {
1018085328eeSLawrence D'Anna   assert(PyErr_Occurred());
1019085328eeSLawrence D'Anna   m_exception_type = m_exception = m_traceback = m_repr_bytes = NULL;
1020085328eeSLawrence D'Anna   PyErr_Fetch(&m_exception_type, &m_exception, &m_traceback);
1021085328eeSLawrence D'Anna   PyErr_NormalizeException(&m_exception_type, &m_exception, &m_traceback);
1022085328eeSLawrence D'Anna   PyErr_Clear();
1023085328eeSLawrence D'Anna   if (m_exception) {
1024085328eeSLawrence D'Anna     PyObject *repr = PyObject_Repr(m_exception);
1025085328eeSLawrence D'Anna     if (repr) {
1026085328eeSLawrence D'Anna       m_repr_bytes = PyUnicode_AsEncodedString(repr, "utf-8", nullptr);
1027085328eeSLawrence D'Anna       if (!m_repr_bytes) {
1028085328eeSLawrence D'Anna         PyErr_Clear();
1029085328eeSLawrence D'Anna       }
1030085328eeSLawrence D'Anna       Py_XDECREF(repr);
1031085328eeSLawrence D'Anna     } else {
1032085328eeSLawrence D'Anna       PyErr_Clear();
1033085328eeSLawrence D'Anna     }
1034085328eeSLawrence D'Anna   }
1035085328eeSLawrence D'Anna   Log *log = GetLogIfAllCategoriesSet(LIBLLDB_LOG_SCRIPT);
1036085328eeSLawrence D'Anna   if (caller)
1037085328eeSLawrence D'Anna     LLDB_LOGF(log, "%s failed with exception: %s", caller, toCString());
1038085328eeSLawrence D'Anna   else
1039085328eeSLawrence D'Anna     LLDB_LOGF(log, "python exception: %s", toCString());
1040085328eeSLawrence D'Anna }
1041085328eeSLawrence D'Anna void PythonException::Restore() {
1042085328eeSLawrence D'Anna   if (m_exception_type && m_exception) {
1043085328eeSLawrence D'Anna     PyErr_Restore(m_exception_type, m_exception, m_traceback);
1044085328eeSLawrence D'Anna   } else {
1045085328eeSLawrence D'Anna     PyErr_SetString(PyExc_Exception, toCString());
1046085328eeSLawrence D'Anna   }
1047085328eeSLawrence D'Anna   m_exception_type = m_exception = m_traceback = NULL;
1048085328eeSLawrence D'Anna }
1049085328eeSLawrence D'Anna 
1050085328eeSLawrence D'Anna PythonException::~PythonException() {
1051085328eeSLawrence D'Anna   Py_XDECREF(m_exception_type);
1052085328eeSLawrence D'Anna   Py_XDECREF(m_exception);
1053085328eeSLawrence D'Anna   Py_XDECREF(m_traceback);
1054085328eeSLawrence D'Anna   Py_XDECREF(m_repr_bytes);
1055085328eeSLawrence D'Anna }
1056085328eeSLawrence D'Anna 
1057085328eeSLawrence D'Anna void PythonException::log(llvm::raw_ostream &OS) const { OS << toCString(); }
1058085328eeSLawrence D'Anna 
1059085328eeSLawrence D'Anna std::error_code PythonException::convertToErrorCode() const {
1060085328eeSLawrence D'Anna   return llvm::inconvertibleErrorCode();
1061085328eeSLawrence D'Anna }
1062085328eeSLawrence D'Anna 
106304edd189SLawrence D'Anna bool PythonException::Matches(PyObject *exc) const {
106404edd189SLawrence D'Anna   return PyErr_GivenExceptionMatches(m_exception_type, exc);
106504edd189SLawrence D'Anna }
106604edd189SLawrence D'Anna 
106704edd189SLawrence D'Anna const char read_exception_script[] = R"(
106804edd189SLawrence D'Anna import sys
106904edd189SLawrence D'Anna from traceback import print_exception
107004edd189SLawrence D'Anna if sys.version_info.major < 3:
107104edd189SLawrence D'Anna   from StringIO import StringIO
107204edd189SLawrence D'Anna else:
107304edd189SLawrence D'Anna   from io import StringIO
107404edd189SLawrence D'Anna def main(exc_type, exc_value, tb):
107504edd189SLawrence D'Anna   f = StringIO()
107604edd189SLawrence D'Anna   print_exception(exc_type, exc_value, tb, file=f)
107704edd189SLawrence D'Anna   return f.getvalue()
107804edd189SLawrence D'Anna )";
107904edd189SLawrence D'Anna 
108004edd189SLawrence D'Anna std::string PythonException::ReadBacktrace() const {
108104edd189SLawrence D'Anna 
108204edd189SLawrence D'Anna   if (!m_traceback)
108304edd189SLawrence D'Anna     return toCString();
108404edd189SLawrence D'Anna 
108504edd189SLawrence D'Anna   // no need to synchronize access to this global, we already have the GIL
108604edd189SLawrence D'Anna   static PythonScript read_exception(read_exception_script);
108704edd189SLawrence D'Anna 
108804edd189SLawrence D'Anna   Expected<std::string> backtrace = As<std::string>(
108904edd189SLawrence D'Anna       read_exception(m_exception_type, m_exception, m_traceback));
109004edd189SLawrence D'Anna 
109104edd189SLawrence D'Anna   if (!backtrace) {
109204edd189SLawrence D'Anna     std::string message =
109304edd189SLawrence D'Anna         std::string(toCString()) + "\n" +
1094e9264b74SKazuaki Ishizaki         "Traceback unavailable, an error occurred while reading it:\n";
109504edd189SLawrence D'Anna     return (message + llvm::toString(backtrace.takeError()));
109604edd189SLawrence D'Anna   }
109704edd189SLawrence D'Anna 
109804edd189SLawrence D'Anna   return std::move(backtrace.get());
109904edd189SLawrence D'Anna }
110004edd189SLawrence D'Anna 
1101085328eeSLawrence D'Anna char PythonException::ID = 0;
1102085328eeSLawrence D'Anna 
110362c9fe42SLawrence D'Anna llvm::Expected<File::OpenOptions>
110462c9fe42SLawrence D'Anna GetOptionsForPyObject(const PythonObject &obj) {
110521b8a8aeSLawrence D'Anna #if PY_MAJOR_VERSION >= 3
110662c9fe42SLawrence D'Anna   auto options = File::OpenOptions(0);
110721b8a8aeSLawrence D'Anna   auto readable = As<bool>(obj.CallMethod("readable"));
110821b8a8aeSLawrence D'Anna   if (!readable)
110921b8a8aeSLawrence D'Anna     return readable.takeError();
111021b8a8aeSLawrence D'Anna   auto writable = As<bool>(obj.CallMethod("writable"));
111121b8a8aeSLawrence D'Anna   if (!writable)
111221b8a8aeSLawrence D'Anna     return writable.takeError();
111321b8a8aeSLawrence D'Anna   if (readable.get())
111421b8a8aeSLawrence D'Anna     options |= File::eOpenOptionRead;
111521b8a8aeSLawrence D'Anna   if (writable.get())
111621b8a8aeSLawrence D'Anna     options |= File::eOpenOptionWrite;
111762c9fe42SLawrence D'Anna   return options;
111821b8a8aeSLawrence D'Anna #else
111921b8a8aeSLawrence D'Anna   PythonString py_mode = obj.GetAttributeValue("mode").AsType<PythonString>();
112062c9fe42SLawrence D'Anna   return File::GetOptionsFromMode(py_mode.GetString());
112121b8a8aeSLawrence D'Anna #endif
112221b8a8aeSLawrence D'Anna }
112321b8a8aeSLawrence D'Anna 
112421b8a8aeSLawrence D'Anna // Base class template for python files.   All it knows how to do
112521b8a8aeSLawrence D'Anna // is hold a reference to the python object and close or flush it
112621b8a8aeSLawrence D'Anna // when the File is closed.
112721b8a8aeSLawrence D'Anna namespace {
112821b8a8aeSLawrence D'Anna template <typename Base> class OwnedPythonFile : public Base {
112921b8a8aeSLawrence D'Anna public:
113021b8a8aeSLawrence D'Anna   template <typename... Args>
113121b8a8aeSLawrence D'Anna   OwnedPythonFile(const PythonFile &file, bool borrowed, Args... args)
113221b8a8aeSLawrence D'Anna       : Base(args...), m_py_obj(file), m_borrowed(borrowed) {
113321b8a8aeSLawrence D'Anna     assert(m_py_obj);
113421b8a8aeSLawrence D'Anna   }
113521b8a8aeSLawrence D'Anna 
113621b8a8aeSLawrence D'Anna   ~OwnedPythonFile() override {
113721b8a8aeSLawrence D'Anna     assert(m_py_obj);
113821b8a8aeSLawrence D'Anna     GIL takeGIL;
113921b8a8aeSLawrence D'Anna     Close();
1140722b6189SLawrence D'Anna     // we need to ensure the python object is released while we still
1141722b6189SLawrence D'Anna     // hold the GIL
114221b8a8aeSLawrence D'Anna     m_py_obj.Reset();
114321b8a8aeSLawrence D'Anna   }
114421b8a8aeSLawrence D'Anna 
114521b8a8aeSLawrence D'Anna   bool IsPythonSideValid() const {
114621b8a8aeSLawrence D'Anna     GIL takeGIL;
114721b8a8aeSLawrence D'Anna     auto closed = As<bool>(m_py_obj.GetAttribute("closed"));
114821b8a8aeSLawrence D'Anna     if (!closed) {
114921b8a8aeSLawrence D'Anna       llvm::consumeError(closed.takeError());
115021b8a8aeSLawrence D'Anna       return false;
115121b8a8aeSLawrence D'Anna     }
115221b8a8aeSLawrence D'Anna     return !closed.get();
115321b8a8aeSLawrence D'Anna   }
115421b8a8aeSLawrence D'Anna 
115521b8a8aeSLawrence D'Anna   bool IsValid() const override {
115621b8a8aeSLawrence D'Anna     return IsPythonSideValid() && Base::IsValid();
115721b8a8aeSLawrence D'Anna   }
115821b8a8aeSLawrence D'Anna 
115921b8a8aeSLawrence D'Anna   Status Close() override {
116021b8a8aeSLawrence D'Anna     assert(m_py_obj);
116121b8a8aeSLawrence D'Anna     Status py_error, base_error;
116221b8a8aeSLawrence D'Anna     GIL takeGIL;
116321b8a8aeSLawrence D'Anna     if (!m_borrowed) {
116421b8a8aeSLawrence D'Anna       auto r = m_py_obj.CallMethod("close");
116521b8a8aeSLawrence D'Anna       if (!r)
116621b8a8aeSLawrence D'Anna         py_error = Status(r.takeError());
116721b8a8aeSLawrence D'Anna     }
116821b8a8aeSLawrence D'Anna     base_error = Base::Close();
116921b8a8aeSLawrence D'Anna     if (py_error.Fail())
117021b8a8aeSLawrence D'Anna       return py_error;
117121b8a8aeSLawrence D'Anna     return base_error;
117221b8a8aeSLawrence D'Anna   };
117321b8a8aeSLawrence D'Anna 
1174d9b553ecSLawrence D'Anna   PyObject *GetPythonObject() const {
1175d9b553ecSLawrence D'Anna     assert(m_py_obj.IsValid());
1176d9b553ecSLawrence D'Anna     return m_py_obj.get();
1177d9b553ecSLawrence D'Anna   }
1178d9b553ecSLawrence D'Anna 
1179d9b553ecSLawrence D'Anna   static bool classof(const File *file) = delete;
1180d9b553ecSLawrence D'Anna 
118121b8a8aeSLawrence D'Anna protected:
118221b8a8aeSLawrence D'Anna   PythonFile m_py_obj;
118321b8a8aeSLawrence D'Anna   bool m_borrowed;
118421b8a8aeSLawrence D'Anna };
118521b8a8aeSLawrence D'Anna } // namespace
118621b8a8aeSLawrence D'Anna 
118721b8a8aeSLawrence D'Anna // A SimplePythonFile is a OwnedPythonFile that just does all I/O as
118821b8a8aeSLawrence D'Anna // a NativeFile
118921b8a8aeSLawrence D'Anna namespace {
119021b8a8aeSLawrence D'Anna class SimplePythonFile : public OwnedPythonFile<NativeFile> {
119121b8a8aeSLawrence D'Anna public:
119221b8a8aeSLawrence D'Anna   SimplePythonFile(const PythonFile &file, bool borrowed, int fd,
119362c9fe42SLawrence D'Anna                    File::OpenOptions options)
119421b8a8aeSLawrence D'Anna       : OwnedPythonFile(file, borrowed, fd, options, false) {}
1195d9b553ecSLawrence D'Anna 
1196d9b553ecSLawrence D'Anna   static char ID;
1197d9b553ecSLawrence D'Anna   bool isA(const void *classID) const override {
1198d9b553ecSLawrence D'Anna     return classID == &ID || NativeFile::isA(classID);
1199d9b553ecSLawrence D'Anna   }
1200d9b553ecSLawrence D'Anna   static bool classof(const File *file) { return file->isA(&ID); }
120121b8a8aeSLawrence D'Anna };
1202d9b553ecSLawrence D'Anna char SimplePythonFile::ID = 0;
120321b8a8aeSLawrence D'Anna } // namespace
120421b8a8aeSLawrence D'Anna 
120521b8a8aeSLawrence D'Anna #if PY_MAJOR_VERSION >= 3
120621b8a8aeSLawrence D'Anna 
120721b8a8aeSLawrence D'Anna namespace {
120821b8a8aeSLawrence D'Anna class PythonBuffer {
120921b8a8aeSLawrence D'Anna public:
121021b8a8aeSLawrence D'Anna   PythonBuffer &operator=(const PythonBuffer &) = delete;
121121b8a8aeSLawrence D'Anna   PythonBuffer(const PythonBuffer &) = delete;
121221b8a8aeSLawrence D'Anna 
121321b8a8aeSLawrence D'Anna   static Expected<PythonBuffer> Create(PythonObject &obj,
121421b8a8aeSLawrence D'Anna                                        int flags = PyBUF_SIMPLE) {
121521b8a8aeSLawrence D'Anna     Py_buffer py_buffer = {};
121621b8a8aeSLawrence D'Anna     PyObject_GetBuffer(obj.get(), &py_buffer, flags);
121721b8a8aeSLawrence D'Anna     if (!py_buffer.obj)
121821b8a8aeSLawrence D'Anna       return llvm::make_error<PythonException>();
121921b8a8aeSLawrence D'Anna     return PythonBuffer(py_buffer);
122021b8a8aeSLawrence D'Anna   }
122121b8a8aeSLawrence D'Anna 
122221b8a8aeSLawrence D'Anna   PythonBuffer(PythonBuffer &&other) {
122321b8a8aeSLawrence D'Anna     m_buffer = other.m_buffer;
122421b8a8aeSLawrence D'Anna     other.m_buffer.obj = nullptr;
122521b8a8aeSLawrence D'Anna   }
122621b8a8aeSLawrence D'Anna 
122721b8a8aeSLawrence D'Anna   ~PythonBuffer() {
122821b8a8aeSLawrence D'Anna     if (m_buffer.obj)
122921b8a8aeSLawrence D'Anna       PyBuffer_Release(&m_buffer);
123021b8a8aeSLawrence D'Anna   }
123121b8a8aeSLawrence D'Anna 
123221b8a8aeSLawrence D'Anna   Py_buffer &get() { return m_buffer; }
123321b8a8aeSLawrence D'Anna 
123421b8a8aeSLawrence D'Anna private:
123521b8a8aeSLawrence D'Anna   // takes ownership of the buffer.
123621b8a8aeSLawrence D'Anna   PythonBuffer(const Py_buffer &py_buffer) : m_buffer(py_buffer) {}
123721b8a8aeSLawrence D'Anna   Py_buffer m_buffer;
123821b8a8aeSLawrence D'Anna };
123921b8a8aeSLawrence D'Anna } // namespace
124021b8a8aeSLawrence D'Anna 
124121b8a8aeSLawrence D'Anna // Shared methods between TextPythonFile and BinaryPythonFile
124221b8a8aeSLawrence D'Anna namespace {
124321b8a8aeSLawrence D'Anna class PythonIOFile : public OwnedPythonFile<File> {
124421b8a8aeSLawrence D'Anna public:
124521b8a8aeSLawrence D'Anna   PythonIOFile(const PythonFile &file, bool borrowed)
124621b8a8aeSLawrence D'Anna       : OwnedPythonFile(file, borrowed) {}
124721b8a8aeSLawrence D'Anna 
124821b8a8aeSLawrence D'Anna   ~PythonIOFile() override { Close(); }
124921b8a8aeSLawrence D'Anna 
125021b8a8aeSLawrence D'Anna   bool IsValid() const override { return IsPythonSideValid(); }
125121b8a8aeSLawrence D'Anna 
125221b8a8aeSLawrence D'Anna   Status Close() override {
125321b8a8aeSLawrence D'Anna     assert(m_py_obj);
125421b8a8aeSLawrence D'Anna     GIL takeGIL;
125521b8a8aeSLawrence D'Anna     if (m_borrowed)
125621b8a8aeSLawrence D'Anna       return Flush();
125721b8a8aeSLawrence D'Anna     auto r = m_py_obj.CallMethod("close");
125821b8a8aeSLawrence D'Anna     if (!r)
125921b8a8aeSLawrence D'Anna       return Status(r.takeError());
126021b8a8aeSLawrence D'Anna     return Status();
126121b8a8aeSLawrence D'Anna   }
126221b8a8aeSLawrence D'Anna 
126321b8a8aeSLawrence D'Anna   Status Flush() override {
126421b8a8aeSLawrence D'Anna     GIL takeGIL;
126521b8a8aeSLawrence D'Anna     auto r = m_py_obj.CallMethod("flush");
126621b8a8aeSLawrence D'Anna     if (!r)
126721b8a8aeSLawrence D'Anna       return Status(r.takeError());
126821b8a8aeSLawrence D'Anna     return Status();
126921b8a8aeSLawrence D'Anna   }
127021b8a8aeSLawrence D'Anna 
1271d9b553ecSLawrence D'Anna   Expected<File::OpenOptions> GetOptions() const override {
1272d9b553ecSLawrence D'Anna     GIL takeGIL;
1273d9b553ecSLawrence D'Anna     return GetOptionsForPyObject(m_py_obj);
1274d9b553ecSLawrence D'Anna   }
1275d9b553ecSLawrence D'Anna 
1276d9b553ecSLawrence D'Anna   static char ID;
1277d9b553ecSLawrence D'Anna   bool isA(const void *classID) const override {
1278d9b553ecSLawrence D'Anna     return classID == &ID || File::isA(classID);
1279d9b553ecSLawrence D'Anna   }
1280d9b553ecSLawrence D'Anna   static bool classof(const File *file) { return file->isA(&ID); }
128121b8a8aeSLawrence D'Anna };
1282d9b553ecSLawrence D'Anna char PythonIOFile::ID = 0;
128321b8a8aeSLawrence D'Anna } // namespace
128421b8a8aeSLawrence D'Anna 
128521b8a8aeSLawrence D'Anna namespace {
128621b8a8aeSLawrence D'Anna class BinaryPythonFile : public PythonIOFile {
128721b8a8aeSLawrence D'Anna protected:
128821b8a8aeSLawrence D'Anna   int m_descriptor;
128921b8a8aeSLawrence D'Anna 
129021b8a8aeSLawrence D'Anna public:
129121b8a8aeSLawrence D'Anna   BinaryPythonFile(int fd, const PythonFile &file, bool borrowed)
129221b8a8aeSLawrence D'Anna       : PythonIOFile(file, borrowed),
129321b8a8aeSLawrence D'Anna         m_descriptor(File::DescriptorIsValid(fd) ? fd
129421b8a8aeSLawrence D'Anna                                                  : File::kInvalidDescriptor) {}
129521b8a8aeSLawrence D'Anna 
129621b8a8aeSLawrence D'Anna   int GetDescriptor() const override { return m_descriptor; }
129721b8a8aeSLawrence D'Anna 
129821b8a8aeSLawrence D'Anna   Status Write(const void *buf, size_t &num_bytes) override {
129921b8a8aeSLawrence D'Anna     GIL takeGIL;
130021b8a8aeSLawrence D'Anna     PyObject *pybuffer_p = PyMemoryView_FromMemory(
130121b8a8aeSLawrence D'Anna         const_cast<char *>((const char *)buf), num_bytes, PyBUF_READ);
130221b8a8aeSLawrence D'Anna     if (!pybuffer_p)
130321b8a8aeSLawrence D'Anna       return Status(llvm::make_error<PythonException>());
130421b8a8aeSLawrence D'Anna     auto pybuffer = Take<PythonObject>(pybuffer_p);
130521b8a8aeSLawrence D'Anna     num_bytes = 0;
130621b8a8aeSLawrence D'Anna     auto bytes_written = As<long long>(m_py_obj.CallMethod("write", pybuffer));
130721b8a8aeSLawrence D'Anna     if (!bytes_written)
130821b8a8aeSLawrence D'Anna       return Status(bytes_written.takeError());
130921b8a8aeSLawrence D'Anna     if (bytes_written.get() < 0)
131021b8a8aeSLawrence D'Anna       return Status(".write() method returned a negative number!");
131121b8a8aeSLawrence D'Anna     static_assert(sizeof(long long) >= sizeof(size_t), "overflow");
131221b8a8aeSLawrence D'Anna     num_bytes = bytes_written.get();
131321b8a8aeSLawrence D'Anna     return Status();
131421b8a8aeSLawrence D'Anna   }
131521b8a8aeSLawrence D'Anna 
131621b8a8aeSLawrence D'Anna   Status Read(void *buf, size_t &num_bytes) override {
131721b8a8aeSLawrence D'Anna     GIL takeGIL;
131821b8a8aeSLawrence D'Anna     static_assert(sizeof(long long) >= sizeof(size_t), "overflow");
131921b8a8aeSLawrence D'Anna     auto pybuffer_obj =
132021b8a8aeSLawrence D'Anna         m_py_obj.CallMethod("read", (unsigned long long)num_bytes);
132121b8a8aeSLawrence D'Anna     if (!pybuffer_obj)
132221b8a8aeSLawrence D'Anna       return Status(pybuffer_obj.takeError());
132321b8a8aeSLawrence D'Anna     num_bytes = 0;
132421b8a8aeSLawrence D'Anna     if (pybuffer_obj.get().IsNone()) {
132521b8a8aeSLawrence D'Anna       // EOF
132621b8a8aeSLawrence D'Anna       num_bytes = 0;
132721b8a8aeSLawrence D'Anna       return Status();
132821b8a8aeSLawrence D'Anna     }
132921b8a8aeSLawrence D'Anna     auto pybuffer = PythonBuffer::Create(pybuffer_obj.get());
133021b8a8aeSLawrence D'Anna     if (!pybuffer)
133121b8a8aeSLawrence D'Anna       return Status(pybuffer.takeError());
133221b8a8aeSLawrence D'Anna     memcpy(buf, pybuffer.get().get().buf, pybuffer.get().get().len);
133321b8a8aeSLawrence D'Anna     num_bytes = pybuffer.get().get().len;
133421b8a8aeSLawrence D'Anna     return Status();
133521b8a8aeSLawrence D'Anna   }
133621b8a8aeSLawrence D'Anna };
133721b8a8aeSLawrence D'Anna } // namespace
133821b8a8aeSLawrence D'Anna 
133921b8a8aeSLawrence D'Anna namespace {
134021b8a8aeSLawrence D'Anna class TextPythonFile : public PythonIOFile {
134121b8a8aeSLawrence D'Anna protected:
134221b8a8aeSLawrence D'Anna   int m_descriptor;
134321b8a8aeSLawrence D'Anna 
134421b8a8aeSLawrence D'Anna public:
134521b8a8aeSLawrence D'Anna   TextPythonFile(int fd, const PythonFile &file, bool borrowed)
134621b8a8aeSLawrence D'Anna       : PythonIOFile(file, borrowed),
134721b8a8aeSLawrence D'Anna         m_descriptor(File::DescriptorIsValid(fd) ? fd
134821b8a8aeSLawrence D'Anna                                                  : File::kInvalidDescriptor) {}
134921b8a8aeSLawrence D'Anna 
135021b8a8aeSLawrence D'Anna   int GetDescriptor() const override { return m_descriptor; }
135121b8a8aeSLawrence D'Anna 
135221b8a8aeSLawrence D'Anna   Status Write(const void *buf, size_t &num_bytes) override {
135321b8a8aeSLawrence D'Anna     GIL takeGIL;
135421b8a8aeSLawrence D'Anna     auto pystring =
135521b8a8aeSLawrence D'Anna         PythonString::FromUTF8(llvm::StringRef((const char *)buf, num_bytes));
135621b8a8aeSLawrence D'Anna     if (!pystring)
135721b8a8aeSLawrence D'Anna       return Status(pystring.takeError());
135821b8a8aeSLawrence D'Anna     num_bytes = 0;
135921b8a8aeSLawrence D'Anna     auto bytes_written =
136021b8a8aeSLawrence D'Anna         As<long long>(m_py_obj.CallMethod("write", pystring.get()));
136121b8a8aeSLawrence D'Anna     if (!bytes_written)
136221b8a8aeSLawrence D'Anna       return Status(bytes_written.takeError());
136321b8a8aeSLawrence D'Anna     if (bytes_written.get() < 0)
136421b8a8aeSLawrence D'Anna       return Status(".write() method returned a negative number!");
136521b8a8aeSLawrence D'Anna     static_assert(sizeof(long long) >= sizeof(size_t), "overflow");
136621b8a8aeSLawrence D'Anna     num_bytes = bytes_written.get();
136721b8a8aeSLawrence D'Anna     return Status();
136821b8a8aeSLawrence D'Anna   }
136921b8a8aeSLawrence D'Anna 
137021b8a8aeSLawrence D'Anna   Status Read(void *buf, size_t &num_bytes) override {
137121b8a8aeSLawrence D'Anna     GIL takeGIL;
137221b8a8aeSLawrence D'Anna     size_t num_chars = num_bytes / 6;
137321b8a8aeSLawrence D'Anna     size_t orig_num_bytes = num_bytes;
137421b8a8aeSLawrence D'Anna     num_bytes = 0;
137521b8a8aeSLawrence D'Anna     if (orig_num_bytes < 6) {
137621b8a8aeSLawrence D'Anna       return Status("can't read less than 6 bytes from a utf8 text stream");
137721b8a8aeSLawrence D'Anna     }
137821b8a8aeSLawrence D'Anna     auto pystring = As<PythonString>(
137921b8a8aeSLawrence D'Anna         m_py_obj.CallMethod("read", (unsigned long long)num_chars));
138021b8a8aeSLawrence D'Anna     if (!pystring)
138121b8a8aeSLawrence D'Anna       return Status(pystring.takeError());
138221b8a8aeSLawrence D'Anna     if (pystring.get().IsNone()) {
138321b8a8aeSLawrence D'Anna       // EOF
138421b8a8aeSLawrence D'Anna       return Status();
138521b8a8aeSLawrence D'Anna     }
138621b8a8aeSLawrence D'Anna     auto stringref = pystring.get().AsUTF8();
138721b8a8aeSLawrence D'Anna     if (!stringref)
138821b8a8aeSLawrence D'Anna       return Status(stringref.takeError());
138921b8a8aeSLawrence D'Anna     num_bytes = stringref.get().size();
139021b8a8aeSLawrence D'Anna     memcpy(buf, stringref.get().begin(), num_bytes);
139121b8a8aeSLawrence D'Anna     return Status();
139221b8a8aeSLawrence D'Anna   }
139321b8a8aeSLawrence D'Anna };
139421b8a8aeSLawrence D'Anna } // namespace
139521b8a8aeSLawrence D'Anna 
139621b8a8aeSLawrence D'Anna #endif
139721b8a8aeSLawrence D'Anna 
139821b8a8aeSLawrence D'Anna llvm::Expected<FileSP> PythonFile::ConvertToFile(bool borrowed) {
139921b8a8aeSLawrence D'Anna   if (!IsValid())
140021b8a8aeSLawrence D'Anna     return llvm::createStringError(llvm::inconvertibleErrorCode(),
140121b8a8aeSLawrence D'Anna                                    "invalid PythonFile");
140221b8a8aeSLawrence D'Anna 
140321b8a8aeSLawrence D'Anna   int fd = PyObject_AsFileDescriptor(m_py_obj);
140421b8a8aeSLawrence D'Anna   if (fd < 0) {
140521b8a8aeSLawrence D'Anna     PyErr_Clear();
140621b8a8aeSLawrence D'Anna     return ConvertToFileForcingUseOfScriptingIOMethods(borrowed);
140721b8a8aeSLawrence D'Anna   }
140821b8a8aeSLawrence D'Anna   auto options = GetOptionsForPyObject(*this);
140921b8a8aeSLawrence D'Anna   if (!options)
141021b8a8aeSLawrence D'Anna     return options.takeError();
141121b8a8aeSLawrence D'Anna 
1412267cc329SMichal Gorny   if (options.get() & File::eOpenOptionWrite) {
141321b8a8aeSLawrence D'Anna     // LLDB and python will not share I/O buffers.  We should probably
141421b8a8aeSLawrence D'Anna     // flush the python buffers now.
141521b8a8aeSLawrence D'Anna     auto r = CallMethod("flush");
141621b8a8aeSLawrence D'Anna     if (!r)
141721b8a8aeSLawrence D'Anna       return r.takeError();
1418267cc329SMichal Gorny   }
141921b8a8aeSLawrence D'Anna 
142021b8a8aeSLawrence D'Anna   FileSP file_sp;
142121b8a8aeSLawrence D'Anna   if (borrowed) {
142221b8a8aeSLawrence D'Anna     // In this case we we don't need to retain the python
142321b8a8aeSLawrence D'Anna     // object at all.
142421b8a8aeSLawrence D'Anna     file_sp = std::make_shared<NativeFile>(fd, options.get(), false);
142521b8a8aeSLawrence D'Anna   } else {
142621b8a8aeSLawrence D'Anna     file_sp = std::static_pointer_cast<File>(
142721b8a8aeSLawrence D'Anna         std::make_shared<SimplePythonFile>(*this, borrowed, fd, options.get()));
142821b8a8aeSLawrence D'Anna   }
142921b8a8aeSLawrence D'Anna   if (!file_sp->IsValid())
143021b8a8aeSLawrence D'Anna     return llvm::createStringError(llvm::inconvertibleErrorCode(),
143121b8a8aeSLawrence D'Anna                                    "invalid File");
143221b8a8aeSLawrence D'Anna 
143321b8a8aeSLawrence D'Anna   return file_sp;
143421b8a8aeSLawrence D'Anna }
143521b8a8aeSLawrence D'Anna 
143621b8a8aeSLawrence D'Anna llvm::Expected<FileSP>
143721b8a8aeSLawrence D'Anna PythonFile::ConvertToFileForcingUseOfScriptingIOMethods(bool borrowed) {
143821b8a8aeSLawrence D'Anna 
143921b8a8aeSLawrence D'Anna   assert(!PyErr_Occurred());
144021b8a8aeSLawrence D'Anna 
144121b8a8aeSLawrence D'Anna   if (!IsValid())
144221b8a8aeSLawrence D'Anna     return llvm::createStringError(llvm::inconvertibleErrorCode(),
144321b8a8aeSLawrence D'Anna                                    "invalid PythonFile");
144421b8a8aeSLawrence D'Anna 
144521b8a8aeSLawrence D'Anna #if PY_MAJOR_VERSION < 3
144621b8a8aeSLawrence D'Anna 
144721b8a8aeSLawrence D'Anna   return llvm::createStringError(llvm::inconvertibleErrorCode(),
144821b8a8aeSLawrence D'Anna                                  "not supported on python 2");
144921b8a8aeSLawrence D'Anna 
145021b8a8aeSLawrence D'Anna #else
145121b8a8aeSLawrence D'Anna 
145221b8a8aeSLawrence D'Anna   int fd = PyObject_AsFileDescriptor(m_py_obj);
145321b8a8aeSLawrence D'Anna   if (fd < 0) {
145421b8a8aeSLawrence D'Anna     PyErr_Clear();
145521b8a8aeSLawrence D'Anna     fd = File::kInvalidDescriptor;
145621b8a8aeSLawrence D'Anna   }
145721b8a8aeSLawrence D'Anna 
145821b8a8aeSLawrence D'Anna   auto io_module = PythonModule::Import("io");
145921b8a8aeSLawrence D'Anna   if (!io_module)
146021b8a8aeSLawrence D'Anna     return io_module.takeError();
146121b8a8aeSLawrence D'Anna   auto textIOBase = io_module.get().Get("TextIOBase");
146221b8a8aeSLawrence D'Anna   if (!textIOBase)
146321b8a8aeSLawrence D'Anna     return textIOBase.takeError();
146421b8a8aeSLawrence D'Anna   auto rawIOBase = io_module.get().Get("RawIOBase");
146521b8a8aeSLawrence D'Anna   if (!rawIOBase)
146621b8a8aeSLawrence D'Anna     return rawIOBase.takeError();
146721b8a8aeSLawrence D'Anna   auto bufferedIOBase = io_module.get().Get("BufferedIOBase");
146821b8a8aeSLawrence D'Anna   if (!bufferedIOBase)
146921b8a8aeSLawrence D'Anna     return bufferedIOBase.takeError();
147021b8a8aeSLawrence D'Anna 
147121b8a8aeSLawrence D'Anna   FileSP file_sp;
147221b8a8aeSLawrence D'Anna 
147321b8a8aeSLawrence D'Anna   auto isTextIO = IsInstance(textIOBase.get());
147421b8a8aeSLawrence D'Anna   if (!isTextIO)
147521b8a8aeSLawrence D'Anna     return isTextIO.takeError();
147621b8a8aeSLawrence D'Anna   if (isTextIO.get())
147721b8a8aeSLawrence D'Anna     file_sp = std::static_pointer_cast<File>(
147821b8a8aeSLawrence D'Anna         std::make_shared<TextPythonFile>(fd, *this, borrowed));
147921b8a8aeSLawrence D'Anna 
148021b8a8aeSLawrence D'Anna   auto isRawIO = IsInstance(rawIOBase.get());
148121b8a8aeSLawrence D'Anna   if (!isRawIO)
148221b8a8aeSLawrence D'Anna     return isRawIO.takeError();
148321b8a8aeSLawrence D'Anna   auto isBufferedIO = IsInstance(bufferedIOBase.get());
148421b8a8aeSLawrence D'Anna   if (!isBufferedIO)
148521b8a8aeSLawrence D'Anna     return isBufferedIO.takeError();
148621b8a8aeSLawrence D'Anna 
148721b8a8aeSLawrence D'Anna   if (isRawIO.get() || isBufferedIO.get()) {
148821b8a8aeSLawrence D'Anna     file_sp = std::static_pointer_cast<File>(
148921b8a8aeSLawrence D'Anna         std::make_shared<BinaryPythonFile>(fd, *this, borrowed));
149021b8a8aeSLawrence D'Anna   }
149121b8a8aeSLawrence D'Anna 
149221b8a8aeSLawrence D'Anna   if (!file_sp)
149321b8a8aeSLawrence D'Anna     return llvm::createStringError(llvm::inconvertibleErrorCode(),
149421b8a8aeSLawrence D'Anna                                    "python file is neither text nor binary");
149521b8a8aeSLawrence D'Anna 
149621b8a8aeSLawrence D'Anna   if (!file_sp->IsValid())
149721b8a8aeSLawrence D'Anna     return llvm::createStringError(llvm::inconvertibleErrorCode(),
149821b8a8aeSLawrence D'Anna                                    "invalid File");
149921b8a8aeSLawrence D'Anna 
150021b8a8aeSLawrence D'Anna   return file_sp;
150121b8a8aeSLawrence D'Anna 
150221b8a8aeSLawrence D'Anna #endif
150321b8a8aeSLawrence D'Anna }
150421b8a8aeSLawrence D'Anna 
1505d9b553ecSLawrence D'Anna Expected<PythonFile> PythonFile::FromFile(File &file, const char *mode) {
1506d9b553ecSLawrence D'Anna   if (!file.IsValid())
1507d9b553ecSLawrence D'Anna     return llvm::createStringError(llvm::inconvertibleErrorCode(),
1508d9b553ecSLawrence D'Anna                                    "invalid file");
1509d9b553ecSLawrence D'Anna 
1510d9b553ecSLawrence D'Anna   if (auto *simple = llvm::dyn_cast<SimplePythonFile>(&file))
1511d9b553ecSLawrence D'Anna     return Retain<PythonFile>(simple->GetPythonObject());
1512d9b553ecSLawrence D'Anna #if PY_MAJOR_VERSION >= 3
1513d9b553ecSLawrence D'Anna   if (auto *pythonio = llvm::dyn_cast<PythonIOFile>(&file))
1514d9b553ecSLawrence D'Anna     return Retain<PythonFile>(pythonio->GetPythonObject());
1515d9b553ecSLawrence D'Anna #endif
1516d9b553ecSLawrence D'Anna 
1517d9b553ecSLawrence D'Anna   if (!mode) {
1518d9b553ecSLawrence D'Anna     auto m = file.GetOpenMode();
1519d9b553ecSLawrence D'Anna     if (!m)
1520d9b553ecSLawrence D'Anna       return m.takeError();
1521d9b553ecSLawrence D'Anna     mode = m.get();
1522d9b553ecSLawrence D'Anna   }
1523d9b553ecSLawrence D'Anna 
1524d9b553ecSLawrence D'Anna   PyObject *file_obj;
1525d9b553ecSLawrence D'Anna #if PY_MAJOR_VERSION >= 3
1526d9b553ecSLawrence D'Anna   file_obj = PyFile_FromFd(file.GetDescriptor(), nullptr, mode, -1, nullptr,
15273071ebf7SLawrence D'Anna                            "ignore", nullptr, /*closefd=*/0);
1528d9b553ecSLawrence D'Anna #else
15293071ebf7SLawrence D'Anna   // I'd like to pass ::fflush here if the file is writable,  so that
15303071ebf7SLawrence D'Anna   // when the python side destructs the file object it will be flushed.
15313071ebf7SLawrence D'Anna   // However, this would be dangerous.    It can cause fflush to be called
15323071ebf7SLawrence D'Anna   // after fclose if the python program keeps a reference to the file after
15333071ebf7SLawrence D'Anna   // the original lldb_private::File has been destructed.
15343071ebf7SLawrence D'Anna   //
15353071ebf7SLawrence D'Anna   // It's all well and good to ask a python program not to use a closed file
15363071ebf7SLawrence D'Anna   // but asking a python program to make sure objects get released in a
15373071ebf7SLawrence D'Anna   // particular order is not safe.
15383071ebf7SLawrence D'Anna   //
15393071ebf7SLawrence D'Anna   // The tradeoff here is that if a python 2 program wants to make sure this
15403071ebf7SLawrence D'Anna   // file gets flushed, they'll have to do it explicitly or wait untill the
15413071ebf7SLawrence D'Anna   // original lldb File itself gets flushed.
15426a93a12aSLawrence D'Anna   file_obj = PyFile_FromFile(file.GetStream(), py2_const_cast(""),
15433071ebf7SLawrence D'Anna                              py2_const_cast(mode), [](FILE *) { return 0; });
1544d9b553ecSLawrence D'Anna #endif
1545d9b553ecSLawrence D'Anna 
1546d9b553ecSLawrence D'Anna   if (!file_obj)
1547d9b553ecSLawrence D'Anna     return exception();
1548d9b553ecSLawrence D'Anna 
1549d9b553ecSLawrence D'Anna   return Take<PythonFile>(file_obj);
1550d9b553ecSLawrence D'Anna }
1551d9b553ecSLawrence D'Anna 
155204edd189SLawrence D'Anna Error PythonScript::Init() {
155304edd189SLawrence D'Anna   if (function.IsValid())
155404edd189SLawrence D'Anna     return Error::success();
155504edd189SLawrence D'Anna 
155604edd189SLawrence D'Anna   PythonDictionary globals(PyInitialValue::Empty);
155704edd189SLawrence D'Anna   auto builtins = PythonModule::BuiltinsModule();
155804edd189SLawrence D'Anna   if (Error error = globals.SetItem("__builtins__", builtins))
155904edd189SLawrence D'Anna     return error;
156004edd189SLawrence D'Anna   PyObject *o =
156104edd189SLawrence D'Anna       PyRun_String(script, Py_file_input, globals.get(), globals.get());
156204edd189SLawrence D'Anna   if (!o)
156304edd189SLawrence D'Anna     return exception();
156404edd189SLawrence D'Anna   Take<PythonObject>(o);
156504edd189SLawrence D'Anna   auto f = As<PythonCallable>(globals.GetItem("main"));
156604edd189SLawrence D'Anna   if (!f)
156704edd189SLawrence D'Anna     return f.takeError();
156804edd189SLawrence D'Anna   function = std::move(f.get());
156904edd189SLawrence D'Anna 
157004edd189SLawrence D'Anna   return Error::success();
157104edd189SLawrence D'Anna }
157204edd189SLawrence D'Anna 
157304edd189SLawrence D'Anna llvm::Expected<PythonObject>
157404edd189SLawrence D'Anna python::runStringOneLine(const llvm::Twine &string,
157504edd189SLawrence D'Anna                          const PythonDictionary &globals,
157604edd189SLawrence D'Anna                          const PythonDictionary &locals) {
157704edd189SLawrence D'Anna   if (!globals.IsValid() || !locals.IsValid())
157804edd189SLawrence D'Anna     return nullDeref();
157904edd189SLawrence D'Anna 
158004edd189SLawrence D'Anna   PyObject *code =
158104edd189SLawrence D'Anna       Py_CompileString(NullTerminated(string), "<string>", Py_eval_input);
158204edd189SLawrence D'Anna   if (!code) {
158304edd189SLawrence D'Anna     PyErr_Clear();
158404edd189SLawrence D'Anna     code =
158504edd189SLawrence D'Anna         Py_CompileString(NullTerminated(string), "<string>", Py_single_input);
158604edd189SLawrence D'Anna   }
158704edd189SLawrence D'Anna   if (!code)
158804edd189SLawrence D'Anna     return exception();
158904edd189SLawrence D'Anna   auto code_ref = Take<PythonObject>(code);
159004edd189SLawrence D'Anna 
159104edd189SLawrence D'Anna #if PY_MAJOR_VERSION < 3
159204edd189SLawrence D'Anna   PyObject *result =
159304edd189SLawrence D'Anna       PyEval_EvalCode((PyCodeObject *)code, globals.get(), locals.get());
159404edd189SLawrence D'Anna #else
159504edd189SLawrence D'Anna   PyObject *result = PyEval_EvalCode(code, globals.get(), locals.get());
159604edd189SLawrence D'Anna #endif
159704edd189SLawrence D'Anna 
159804edd189SLawrence D'Anna   if (!result)
159904edd189SLawrence D'Anna     return exception();
160004edd189SLawrence D'Anna 
160104edd189SLawrence D'Anna   return Take<PythonObject>(result);
160204edd189SLawrence D'Anna }
160304edd189SLawrence D'Anna 
160404edd189SLawrence D'Anna llvm::Expected<PythonObject>
160504edd189SLawrence D'Anna python::runStringMultiLine(const llvm::Twine &string,
160604edd189SLawrence D'Anna                            const PythonDictionary &globals,
160704edd189SLawrence D'Anna                            const PythonDictionary &locals) {
160804edd189SLawrence D'Anna   if (!globals.IsValid() || !locals.IsValid())
160904edd189SLawrence D'Anna     return nullDeref();
161004edd189SLawrence D'Anna   PyObject *result = PyRun_String(NullTerminated(string), Py_file_input,
161104edd189SLawrence D'Anna                                   globals.get(), locals.get());
161204edd189SLawrence D'Anna   if (!result)
161304edd189SLawrence D'Anna     return exception();
161404edd189SLawrence D'Anna   return Take<PythonObject>(result);
161504edd189SLawrence D'Anna }
161604edd189SLawrence D'Anna 
1617d68983e3SPavel Labath #endif
1618