1bcadb5a3SPavel Labath //===-- PythonDataObjects.cpp -----------------------------------*- C++ -*-===//
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 
9d68983e3SPavel Labath #ifdef LLDB_DISABLE_PYTHON
10d68983e3SPavel Labath 
11d68983e3SPavel Labath // Python is disabled in this build
12d68983e3SPavel Labath 
13d68983e3SPavel Labath #else
14d68983e3SPavel Labath 
152c1f46dcSZachary Turner #include "PythonDataObjects.h"
162c1f46dcSZachary Turner #include "ScriptInterpreterPython.h"
172c1f46dcSZachary Turner 
182c1f46dcSZachary Turner #include "lldb/Host/File.h"
19190fadcdSZachary Turner #include "lldb/Host/FileSystem.h"
202c1f46dcSZachary Turner #include "lldb/Interpreter/ScriptInterpreter.h"
21085328eeSLawrence D'Anna #include "lldb/Utility/Log.h"
22bf9a7730SZachary Turner #include "lldb/Utility/Stream.h"
232c1f46dcSZachary Turner 
249a6c7572SJonas Devlieghere #include "llvm/ADT/StringSwitch.h"
25190fadcdSZachary Turner #include "llvm/Support/ConvertUTF.h"
262819136fSMichal Gorny #include "llvm/Support/Errno.h"
27190fadcdSZachary Turner 
282c1f46dcSZachary Turner #include <stdio.h>
292c1f46dcSZachary Turner 
302c1f46dcSZachary Turner using namespace lldb_private;
312c1f46dcSZachary Turner using namespace lldb;
32085328eeSLawrence D'Anna using namespace lldb_private::python;
33085328eeSLawrence D'Anna using llvm::Error;
34085328eeSLawrence D'Anna using llvm::Expected;
35085328eeSLawrence D'Anna 
36085328eeSLawrence D'Anna template <> Expected<bool> python::As<bool>(Expected<PythonObject> &&obj) {
37085328eeSLawrence D'Anna   if (!obj)
38085328eeSLawrence D'Anna     return obj.takeError();
39085328eeSLawrence D'Anna   return obj.get().IsTrue();
40085328eeSLawrence D'Anna }
41085328eeSLawrence D'Anna 
42085328eeSLawrence D'Anna template <>
43085328eeSLawrence D'Anna Expected<long long> python::As<long long>(Expected<PythonObject> &&obj) {
44085328eeSLawrence D'Anna   if (!obj)
45085328eeSLawrence D'Anna     return obj.takeError();
46085328eeSLawrence D'Anna   return obj.get().AsLongLong();
47085328eeSLawrence D'Anna }
482c1f46dcSZachary Turner 
492783d817SJonas Devlieghere void StructuredPythonObject::Serialize(llvm::json::OStream &s) const {
502783d817SJonas Devlieghere   s.value(llvm::formatv("Python Obj: {0:X}", GetValue()).str());
512c1f46dcSZachary Turner }
522c1f46dcSZachary Turner 
532c1f46dcSZachary Turner // PythonObject
542c1f46dcSZachary Turner 
55b9c1b51eSKate Stone void PythonObject::Dump(Stream &strm) const {
56b9c1b51eSKate Stone   if (m_py_obj) {
572819136fSMichal Gorny     FILE *file = llvm::sys::RetryAfterSignal(nullptr, ::tmpfile);
58b9c1b51eSKate Stone     if (file) {
592c1f46dcSZachary Turner       ::PyObject_Print(m_py_obj, file, 0);
602c1f46dcSZachary Turner       const long length = ftell(file);
61b9c1b51eSKate Stone       if (length) {
622c1f46dcSZachary Turner         ::rewind(file);
632c1f46dcSZachary Turner         std::vector<char> file_contents(length, '\0');
64b9c1b51eSKate Stone         const size_t length_read =
65b9c1b51eSKate Stone             ::fread(file_contents.data(), 1, file_contents.size(), file);
662c1f46dcSZachary Turner         if (length_read > 0)
672c1f46dcSZachary Turner           strm.Write(file_contents.data(), length_read);
682c1f46dcSZachary Turner       }
692c1f46dcSZachary Turner       ::fclose(file);
702c1f46dcSZachary Turner     }
71b9c1b51eSKate Stone   } else
722c1f46dcSZachary Turner     strm.PutCString("NULL");
732c1f46dcSZachary Turner }
742c1f46dcSZachary Turner 
75b9c1b51eSKate Stone PyObjectType PythonObject::GetObjectType() const {
76f8b22f8fSZachary Turner   if (!IsAllocated())
772c1f46dcSZachary Turner     return PyObjectType::None;
782c1f46dcSZachary Turner 
797841efbbSZachary Turner   if (PythonModule::Check(m_py_obj))
807841efbbSZachary Turner     return PyObjectType::Module;
8118426935SZachary Turner   if (PythonList::Check(m_py_obj))
822c1f46dcSZachary Turner     return PyObjectType::List;
83a1405147SZachary Turner   if (PythonTuple::Check(m_py_obj))
84a1405147SZachary Turner     return PyObjectType::Tuple;
8518426935SZachary Turner   if (PythonDictionary::Check(m_py_obj))
862c1f46dcSZachary Turner     return PyObjectType::Dictionary;
8718426935SZachary Turner   if (PythonString::Check(m_py_obj))
8822c8efcdSZachary Turner     return PyObjectType::String;
895a72c02bSZachary Turner #if PY_MAJOR_VERSION >= 3
905a72c02bSZachary Turner   if (PythonBytes::Check(m_py_obj))
915a72c02bSZachary Turner     return PyObjectType::Bytes;
925a72c02bSZachary Turner #endif
93f9d6d204SZachary Turner   if (PythonByteArray::Check(m_py_obj))
94f9d6d204SZachary Turner     return PyObjectType::ByteArray;
95b81d715cSTatyana Krasnukha   if (PythonBoolean::Check(m_py_obj))
96b81d715cSTatyana Krasnukha     return PyObjectType::Boolean;
9718426935SZachary Turner   if (PythonInteger::Check(m_py_obj))
9822c8efcdSZachary Turner     return PyObjectType::Integer;
999c40264fSZachary Turner   if (PythonFile::Check(m_py_obj))
1009c40264fSZachary Turner     return PyObjectType::File;
101a1405147SZachary Turner   if (PythonCallable::Check(m_py_obj))
102a1405147SZachary Turner     return PyObjectType::Callable;
1032c1f46dcSZachary Turner   return PyObjectType::Unknown;
1042c1f46dcSZachary Turner }
1052c1f46dcSZachary Turner 
106b9c1b51eSKate Stone PythonString PythonObject::Repr() const {
1072c1f46dcSZachary Turner   if (!m_py_obj)
1082c1f46dcSZachary Turner     return PythonString();
1092c1f46dcSZachary Turner   PyObject *repr = PyObject_Repr(m_py_obj);
1102c1f46dcSZachary Turner   if (!repr)
1112c1f46dcSZachary Turner     return PythonString();
112f8b22f8fSZachary Turner   return PythonString(PyRefType::Owned, repr);
1132c1f46dcSZachary Turner }
1142c1f46dcSZachary Turner 
115b9c1b51eSKate Stone PythonString PythonObject::Str() const {
1162c1f46dcSZachary Turner   if (!m_py_obj)
1172c1f46dcSZachary Turner     return PythonString();
1182c1f46dcSZachary Turner   PyObject *str = PyObject_Str(m_py_obj);
1192c1f46dcSZachary Turner   if (!str)
1202c1f46dcSZachary Turner     return PythonString();
121f8b22f8fSZachary Turner   return PythonString(PyRefType::Owned, str);
1222c1f46dcSZachary Turner }
1232c1f46dcSZachary Turner 
1247841efbbSZachary Turner PythonObject
125b9c1b51eSKate Stone PythonObject::ResolveNameWithDictionary(llvm::StringRef name,
126b9c1b51eSKate Stone                                         const PythonDictionary &dict) {
127c712bac7SJonas Devlieghere   size_t dot_pos = name.find('.');
128a1405147SZachary Turner   llvm::StringRef piece = name.substr(0, dot_pos);
129a1405147SZachary Turner   PythonObject result = dict.GetItemForKey(PythonString(piece));
130b9c1b51eSKate Stone   if (dot_pos == llvm::StringRef::npos) {
131a1405147SZachary Turner     // There was no dot, we're done.
132a1405147SZachary Turner     return result;
133a1405147SZachary Turner   }
134a1405147SZachary Turner 
135a1405147SZachary Turner   // There was a dot.  The remaining portion of the name should be looked up in
136a1405147SZachary Turner   // the context of the object that was found in the dictionary.
137a1405147SZachary Turner   return result.ResolveName(name.substr(dot_pos + 1));
1387841efbbSZachary Turner }
1397841efbbSZachary Turner 
140b9c1b51eSKate Stone PythonObject PythonObject::ResolveName(llvm::StringRef name) const {
14105097246SAdrian Prantl   // Resolve the name in the context of the specified object.  If, for example,
14205097246SAdrian Prantl   // `this` refers to a PyModule, then this will look for `name` in this
14305097246SAdrian Prantl   // module.  If `this` refers to a PyType, then it will resolve `name` as an
14405097246SAdrian Prantl   // attribute of that type.  If `this` refers to an instance of an object,
14505097246SAdrian Prantl   // then it will resolve `name` as the value of the specified field.
1467841efbbSZachary Turner   //
1477841efbbSZachary Turner   // This function handles dotted names so that, for example, if `m_py_obj`
14805097246SAdrian Prantl   // refers to the `sys` module, and `name` == "path.append", then it will find
14905097246SAdrian Prantl   // the function `sys.path.append`.
1507841efbbSZachary Turner 
151c712bac7SJonas Devlieghere   size_t dot_pos = name.find('.');
152b9c1b51eSKate Stone   if (dot_pos == llvm::StringRef::npos) {
15305097246SAdrian Prantl     // No dots in the name, we should be able to find the value immediately as
15405097246SAdrian Prantl     // an attribute of `m_py_obj`.
1557841efbbSZachary Turner     return GetAttributeValue(name);
1567841efbbSZachary Turner   }
1577841efbbSZachary Turner 
158b9c1b51eSKate Stone   // Look up the first piece of the name, and resolve the rest as a child of
159b9c1b51eSKate Stone   // that.
1607841efbbSZachary Turner   PythonObject parent = ResolveName(name.substr(0, dot_pos));
1617841efbbSZachary Turner   if (!parent.IsAllocated())
1627841efbbSZachary Turner     return PythonObject();
1637841efbbSZachary Turner 
1647841efbbSZachary Turner   // Tail recursion.. should be optimized by the compiler
1657841efbbSZachary Turner   return parent.ResolveName(name.substr(dot_pos + 1));
1667841efbbSZachary Turner }
1677841efbbSZachary Turner 
168b9c1b51eSKate Stone bool PythonObject::HasAttribute(llvm::StringRef attr) const {
1699c40264fSZachary Turner   if (!IsValid())
1709c40264fSZachary Turner     return false;
1719c40264fSZachary Turner   PythonString py_attr(attr);
1729c40264fSZachary Turner   return !!PyObject_HasAttr(m_py_obj, py_attr.get());
1739c40264fSZachary Turner }
1749c40264fSZachary Turner 
175b9c1b51eSKate Stone PythonObject PythonObject::GetAttributeValue(llvm::StringRef attr) const {
1767d6d218eSZachary Turner   if (!IsValid())
1777d6d218eSZachary Turner     return PythonObject();
1787d6d218eSZachary Turner 
1797d6d218eSZachary Turner   PythonString py_attr(attr);
1807d6d218eSZachary Turner   if (!PyObject_HasAttr(m_py_obj, py_attr.get()))
1817d6d218eSZachary Turner     return PythonObject();
1827d6d218eSZachary Turner 
1837d6d218eSZachary Turner   return PythonObject(PyRefType::Owned,
1847d6d218eSZachary Turner                       PyObject_GetAttr(m_py_obj, py_attr.get()));
1857d6d218eSZachary Turner }
1867d6d218eSZachary Turner 
187b9c1b51eSKate Stone StructuredData::ObjectSP PythonObject::CreateStructuredObject() const {
188b9c1b51eSKate Stone   switch (GetObjectType()) {
1892c1f46dcSZachary Turner   case PyObjectType::Dictionary:
190b9c1b51eSKate Stone     return PythonDictionary(PyRefType::Borrowed, m_py_obj)
191b9c1b51eSKate Stone         .CreateStructuredDictionary();
192b81d715cSTatyana Krasnukha   case PyObjectType::Boolean:
193b81d715cSTatyana Krasnukha     return PythonBoolean(PyRefType::Borrowed, m_py_obj)
194b81d715cSTatyana Krasnukha         .CreateStructuredBoolean();
1952c1f46dcSZachary Turner   case PyObjectType::Integer:
196b9c1b51eSKate Stone     return PythonInteger(PyRefType::Borrowed, m_py_obj)
197b9c1b51eSKate Stone         .CreateStructuredInteger();
1982c1f46dcSZachary Turner   case PyObjectType::List:
199f8b22f8fSZachary Turner     return PythonList(PyRefType::Borrowed, m_py_obj).CreateStructuredArray();
2002c1f46dcSZachary Turner   case PyObjectType::String:
201f8b22f8fSZachary Turner     return PythonString(PyRefType::Borrowed, m_py_obj).CreateStructuredString();
2025a72c02bSZachary Turner   case PyObjectType::Bytes:
2035a72c02bSZachary Turner     return PythonBytes(PyRefType::Borrowed, m_py_obj).CreateStructuredString();
204f9d6d204SZachary Turner   case PyObjectType::ByteArray:
205b9c1b51eSKate Stone     return PythonByteArray(PyRefType::Borrowed, m_py_obj)
206b9c1b51eSKate Stone         .CreateStructuredString();
2072c1f46dcSZachary Turner   case PyObjectType::None:
2082c1f46dcSZachary Turner     return StructuredData::ObjectSP();
2092c1f46dcSZachary Turner   default:
2102c1f46dcSZachary Turner     return StructuredData::ObjectSP(new StructuredPythonObject(m_py_obj));
2112c1f46dcSZachary Turner   }
2122c1f46dcSZachary Turner }
2132c1f46dcSZachary Turner 
2142c1f46dcSZachary Turner // PythonString
215b9c1b51eSKate Stone PythonBytes::PythonBytes() : PythonObject() {}
2165a72c02bSZachary Turner 
217b9c1b51eSKate Stone PythonBytes::PythonBytes(llvm::ArrayRef<uint8_t> bytes) : PythonObject() {
2185a72c02bSZachary Turner   SetBytes(bytes);
2195a72c02bSZachary Turner }
2205a72c02bSZachary Turner 
221b9c1b51eSKate Stone PythonBytes::PythonBytes(const uint8_t *bytes, size_t length) : PythonObject() {
2225a72c02bSZachary Turner   SetBytes(llvm::ArrayRef<uint8_t>(bytes, length));
2235a72c02bSZachary Turner }
2245a72c02bSZachary Turner 
225b9c1b51eSKate Stone PythonBytes::PythonBytes(PyRefType type, PyObject *py_obj) : PythonObject() {
2265a72c02bSZachary Turner   Reset(type, py_obj); // Use "Reset()" to ensure that py_obj is a string
2275a72c02bSZachary Turner }
2285a72c02bSZachary Turner 
229b9c1b51eSKate Stone PythonBytes::~PythonBytes() {}
2305a72c02bSZachary Turner 
231b9c1b51eSKate Stone bool PythonBytes::Check(PyObject *py_obj) {
2325a72c02bSZachary Turner   if (!py_obj)
2335a72c02bSZachary Turner     return false;
234a6682a41SJonas Devlieghere   return PyBytes_Check(py_obj);
2355a72c02bSZachary Turner }
2365a72c02bSZachary Turner 
237b9c1b51eSKate Stone void PythonBytes::Reset(PyRefType type, PyObject *py_obj) {
23805097246SAdrian Prantl   // Grab the desired reference type so that if we end up rejecting `py_obj` it
23905097246SAdrian Prantl   // still gets decremented if necessary.
2405a72c02bSZachary Turner   PythonObject result(type, py_obj);
2415a72c02bSZachary Turner 
242b9c1b51eSKate Stone   if (!PythonBytes::Check(py_obj)) {
2435a72c02bSZachary Turner     PythonObject::Reset();
2445a72c02bSZachary Turner     return;
2455a72c02bSZachary Turner   }
2465a72c02bSZachary Turner 
247b9c1b51eSKate Stone   // Calling PythonObject::Reset(const PythonObject&) will lead to stack
24805097246SAdrian Prantl   // overflow since it calls back into the virtual implementation.
2495a72c02bSZachary Turner   PythonObject::Reset(PyRefType::Borrowed, result.get());
2505a72c02bSZachary Turner }
2515a72c02bSZachary Turner 
252b9c1b51eSKate Stone llvm::ArrayRef<uint8_t> PythonBytes::GetBytes() const {
2535a72c02bSZachary Turner   if (!IsValid())
2545a72c02bSZachary Turner     return llvm::ArrayRef<uint8_t>();
2555a72c02bSZachary Turner 
2565a72c02bSZachary Turner   Py_ssize_t size;
2575a72c02bSZachary Turner   char *c;
2585a72c02bSZachary Turner 
2595a72c02bSZachary Turner   PyBytes_AsStringAndSize(m_py_obj, &c, &size);
2605a72c02bSZachary Turner   return llvm::ArrayRef<uint8_t>(reinterpret_cast<uint8_t *>(c), size);
2615a72c02bSZachary Turner }
2625a72c02bSZachary Turner 
263b9c1b51eSKate Stone size_t PythonBytes::GetSize() const {
2645a72c02bSZachary Turner   if (!IsValid())
2655a72c02bSZachary Turner     return 0;
2665a72c02bSZachary Turner   return PyBytes_Size(m_py_obj);
2675a72c02bSZachary Turner }
2685a72c02bSZachary Turner 
269b9c1b51eSKate Stone void PythonBytes::SetBytes(llvm::ArrayRef<uint8_t> bytes) {
2705a72c02bSZachary Turner   const char *data = reinterpret_cast<const char *>(bytes.data());
2715a72c02bSZachary Turner   PyObject *py_bytes = PyBytes_FromStringAndSize(data, bytes.size());
2725a72c02bSZachary Turner   PythonObject::Reset(PyRefType::Owned, py_bytes);
2735a72c02bSZachary Turner }
2745a72c02bSZachary Turner 
275b9c1b51eSKate Stone StructuredData::StringSP PythonBytes::CreateStructuredString() const {
2765a72c02bSZachary Turner   StructuredData::StringSP result(new StructuredData::String);
2775a72c02bSZachary Turner   Py_ssize_t size;
2785a72c02bSZachary Turner   char *c;
2795a72c02bSZachary Turner   PyBytes_AsStringAndSize(m_py_obj, &c, &size);
2805a72c02bSZachary Turner   result->SetValue(std::string(c, size));
2815a72c02bSZachary Turner   return result;
2825a72c02bSZachary Turner }
2835a72c02bSZachary Turner 
284b9c1b51eSKate Stone PythonByteArray::PythonByteArray(llvm::ArrayRef<uint8_t> bytes)
285b9c1b51eSKate Stone     : PythonByteArray(bytes.data(), bytes.size()) {}
286f9d6d204SZachary Turner 
287b9c1b51eSKate Stone PythonByteArray::PythonByteArray(const uint8_t *bytes, size_t length) {
288f9d6d204SZachary Turner   const char *str = reinterpret_cast<const char *>(bytes);
289f9d6d204SZachary Turner   Reset(PyRefType::Owned, PyByteArray_FromStringAndSize(str, length));
290f9d6d204SZachary Turner }
291f9d6d204SZachary Turner 
292b9c1b51eSKate Stone PythonByteArray::PythonByteArray(PyRefType type, PyObject *o) {
293f9d6d204SZachary Turner   Reset(type, o);
294f9d6d204SZachary Turner }
295f9d6d204SZachary Turner 
296b9c1b51eSKate Stone PythonByteArray::PythonByteArray(const PythonBytes &object)
297b9c1b51eSKate Stone     : PythonObject(object) {}
298f9d6d204SZachary Turner 
299b9c1b51eSKate Stone PythonByteArray::~PythonByteArray() {}
300f9d6d204SZachary Turner 
301b9c1b51eSKate Stone bool PythonByteArray::Check(PyObject *py_obj) {
302f9d6d204SZachary Turner   if (!py_obj)
303f9d6d204SZachary Turner     return false;
304a6682a41SJonas Devlieghere   return PyByteArray_Check(py_obj);
305f9d6d204SZachary Turner }
306f9d6d204SZachary Turner 
307b9c1b51eSKate Stone void PythonByteArray::Reset(PyRefType type, PyObject *py_obj) {
30805097246SAdrian Prantl   // Grab the desired reference type so that if we end up rejecting `py_obj` it
30905097246SAdrian Prantl   // still gets decremented if necessary.
310f9d6d204SZachary Turner   PythonObject result(type, py_obj);
311f9d6d204SZachary Turner 
312b9c1b51eSKate Stone   if (!PythonByteArray::Check(py_obj)) {
313f9d6d204SZachary Turner     PythonObject::Reset();
314f9d6d204SZachary Turner     return;
315f9d6d204SZachary Turner   }
316f9d6d204SZachary Turner 
317b9c1b51eSKate Stone   // Calling PythonObject::Reset(const PythonObject&) will lead to stack
31805097246SAdrian Prantl   // overflow since it calls back into the virtual implementation.
319f9d6d204SZachary Turner   PythonObject::Reset(PyRefType::Borrowed, result.get());
320f9d6d204SZachary Turner }
321f9d6d204SZachary Turner 
322b9c1b51eSKate Stone llvm::ArrayRef<uint8_t> PythonByteArray::GetBytes() const {
323f9d6d204SZachary Turner   if (!IsValid())
324f9d6d204SZachary Turner     return llvm::ArrayRef<uint8_t>();
325f9d6d204SZachary Turner 
326f9d6d204SZachary Turner   char *c = PyByteArray_AsString(m_py_obj);
327f9d6d204SZachary Turner   size_t size = GetSize();
328f9d6d204SZachary Turner   return llvm::ArrayRef<uint8_t>(reinterpret_cast<uint8_t *>(c), size);
329f9d6d204SZachary Turner }
330f9d6d204SZachary Turner 
331b9c1b51eSKate Stone size_t PythonByteArray::GetSize() const {
332f9d6d204SZachary Turner   if (!IsValid())
333f9d6d204SZachary Turner     return 0;
334f9d6d204SZachary Turner 
335f9d6d204SZachary Turner   return PyByteArray_Size(m_py_obj);
336f9d6d204SZachary Turner }
337f9d6d204SZachary Turner 
338b9c1b51eSKate Stone StructuredData::StringSP PythonByteArray::CreateStructuredString() const {
339f9d6d204SZachary Turner   StructuredData::StringSP result(new StructuredData::String);
340f9d6d204SZachary Turner   llvm::ArrayRef<uint8_t> bytes = GetBytes();
341f9d6d204SZachary Turner   const char *str = reinterpret_cast<const char *>(bytes.data());
342f9d6d204SZachary Turner   result->SetValue(std::string(str, bytes.size()));
343f9d6d204SZachary Turner   return result;
344f9d6d204SZachary Turner }
345f9d6d204SZachary Turner 
3465a72c02bSZachary Turner // PythonString
3472c1f46dcSZachary Turner 
348085328eeSLawrence D'Anna Expected<PythonString> PythonString::FromUTF8(llvm::StringRef string) {
349085328eeSLawrence D'Anna #if PY_MAJOR_VERSION >= 3
350085328eeSLawrence D'Anna   PyObject *str = PyUnicode_FromStringAndSize(string.data(), string.size());
351085328eeSLawrence D'Anna #else
352085328eeSLawrence D'Anna   PyObject *str = PyString_FromStringAndSize(string.data(), string.size());
353085328eeSLawrence D'Anna #endif
354085328eeSLawrence D'Anna   if (!str)
355085328eeSLawrence D'Anna     return llvm::make_error<PythonException>();
356085328eeSLawrence D'Anna   return Take<PythonString>(str);
357085328eeSLawrence D'Anna }
358085328eeSLawrence D'Anna 
359b9c1b51eSKate Stone PythonString::PythonString(PyRefType type, PyObject *py_obj) : PythonObject() {
360f8b22f8fSZachary Turner   Reset(type, py_obj); // Use "Reset()" to ensure that py_obj is a string
3612c1f46dcSZachary Turner }
3622c1f46dcSZachary Turner 
363b9c1b51eSKate Stone PythonString::PythonString(llvm::StringRef string) : PythonObject() {
36422c8efcdSZachary Turner   SetString(string);
3652c1f46dcSZachary Turner }
3662c1f46dcSZachary Turner 
367b9c1b51eSKate Stone PythonString::PythonString() : PythonObject() {}
3682c1f46dcSZachary Turner 
369b9c1b51eSKate Stone PythonString::~PythonString() {}
3702c1f46dcSZachary Turner 
371b9c1b51eSKate Stone bool PythonString::Check(PyObject *py_obj) {
37222c8efcdSZachary Turner   if (!py_obj)
37322c8efcdSZachary Turner     return false;
37418426935SZachary Turner 
3757d6d218eSZachary Turner   if (PyUnicode_Check(py_obj))
3767d6d218eSZachary Turner     return true;
3777d6d218eSZachary Turner #if PY_MAJOR_VERSION < 3
3787d6d218eSZachary Turner   if (PyString_Check(py_obj))
3797d6d218eSZachary Turner     return true;
38022c8efcdSZachary Turner #endif
3817d6d218eSZachary Turner   return false;
38222c8efcdSZachary Turner }
38322c8efcdSZachary Turner 
384b9c1b51eSKate Stone void PythonString::Reset(PyRefType type, PyObject *py_obj) {
38505097246SAdrian Prantl   // Grab the desired reference type so that if we end up rejecting `py_obj` it
38605097246SAdrian Prantl   // still gets decremented if necessary.
387f8b22f8fSZachary Turner   PythonObject result(type, py_obj);
388f8b22f8fSZachary Turner 
389b9c1b51eSKate Stone   if (!PythonString::Check(py_obj)) {
390f8b22f8fSZachary Turner     PythonObject::Reset();
391f8b22f8fSZachary Turner     return;
39222c8efcdSZachary Turner   }
3937d6d218eSZachary Turner #if PY_MAJOR_VERSION < 3
3947d6d218eSZachary Turner   // In Python 2, Don't store PyUnicode objects directly, because we need
3957d6d218eSZachary Turner   // access to their underlying character buffers which Python 2 doesn't
3967d6d218eSZachary Turner   // provide.
397085328eeSLawrence D'Anna   if (PyUnicode_Check(py_obj)) {
398085328eeSLawrence D'Anna     PyObject *s = PyUnicode_AsUTF8String(result.get());
399085328eeSLawrence D'Anna     if (s == NULL)
400085328eeSLawrence D'Anna       PyErr_Clear();
401085328eeSLawrence D'Anna     result.Reset(PyRefType::Owned, s);
402085328eeSLawrence D'Anna   }
4037d6d218eSZachary Turner #endif
404b9c1b51eSKate Stone   // Calling PythonObject::Reset(const PythonObject&) will lead to stack
40505097246SAdrian Prantl   // overflow since it calls back into the virtual implementation.
406f8b22f8fSZachary Turner   PythonObject::Reset(PyRefType::Borrowed, result.get());
4072c1f46dcSZachary Turner }
4082c1f46dcSZachary Turner 
409b9c1b51eSKate Stone llvm::StringRef PythonString::GetString() const {
410085328eeSLawrence D'Anna   auto s = AsUTF8();
411085328eeSLawrence D'Anna   if (!s) {
412085328eeSLawrence D'Anna     llvm::consumeError(s.takeError());
413085328eeSLawrence D'Anna     return llvm::StringRef("");
414085328eeSLawrence D'Anna   }
415085328eeSLawrence D'Anna   return s.get();
416085328eeSLawrence D'Anna }
417085328eeSLawrence D'Anna 
418085328eeSLawrence D'Anna Expected<llvm::StringRef> PythonString::AsUTF8() const {
41918426935SZachary Turner   if (!IsValid())
420085328eeSLawrence D'Anna     return nullDeref();
42118426935SZachary Turner 
42222c8efcdSZachary Turner   Py_ssize_t size;
4235457b426SPavel Labath   const char *data;
42418426935SZachary Turner 
42518426935SZachary Turner #if PY_MAJOR_VERSION >= 3
4265457b426SPavel Labath   data = PyUnicode_AsUTF8AndSize(m_py_obj, &size);
42718426935SZachary Turner #else
428085328eeSLawrence D'Anna   char *c = NULL;
429085328eeSLawrence D'Anna   int r = PyString_AsStringAndSize(m_py_obj, &c, &size);
430085328eeSLawrence D'Anna   if (r < 0)
431085328eeSLawrence D'Anna     c = NULL;
4325457b426SPavel Labath   data = c;
43318426935SZachary Turner #endif
434085328eeSLawrence D'Anna 
435085328eeSLawrence D'Anna   if (!data)
436085328eeSLawrence D'Anna     return exception();
437085328eeSLawrence D'Anna 
4385457b426SPavel Labath   return llvm::StringRef(data, size);
43922c8efcdSZachary Turner }
4402c1f46dcSZachary Turner 
441b9c1b51eSKate Stone size_t PythonString::GetSize() const {
442b9c1b51eSKate Stone   if (IsValid()) {
44318426935SZachary Turner #if PY_MAJOR_VERSION >= 3
44418426935SZachary Turner     return PyUnicode_GetSize(m_py_obj);
44518426935SZachary Turner #else
44618426935SZachary Turner     return PyString_Size(m_py_obj);
44718426935SZachary Turner #endif
44818426935SZachary Turner   }
4492c1f46dcSZachary Turner   return 0;
4502c1f46dcSZachary Turner }
4512c1f46dcSZachary Turner 
452b9c1b51eSKate Stone void PythonString::SetString(llvm::StringRef string) {
453085328eeSLawrence D'Anna   auto s = FromUTF8(string);
454085328eeSLawrence D'Anna   if (!s) {
455085328eeSLawrence D'Anna     llvm::consumeError(s.takeError());
456085328eeSLawrence D'Anna     Reset();
457085328eeSLawrence D'Anna   } else {
458085328eeSLawrence D'Anna     PythonObject::Reset(std::move(s.get()));
459085328eeSLawrence D'Anna   }
4602c1f46dcSZachary Turner }
4612c1f46dcSZachary Turner 
462b9c1b51eSKate Stone StructuredData::StringSP PythonString::CreateStructuredString() const {
4632c1f46dcSZachary Turner   StructuredData::StringSP result(new StructuredData::String);
4642c1f46dcSZachary Turner   result->SetValue(GetString());
4652c1f46dcSZachary Turner   return result;
4662c1f46dcSZachary Turner }
4672c1f46dcSZachary Turner 
4682c1f46dcSZachary Turner // PythonInteger
4692c1f46dcSZachary Turner 
470b9c1b51eSKate Stone PythonInteger::PythonInteger() : PythonObject() {}
4717d6d218eSZachary Turner 
472f8b22f8fSZachary Turner PythonInteger::PythonInteger(PyRefType type, PyObject *py_obj)
473b9c1b51eSKate Stone     : PythonObject() {
474f8b22f8fSZachary Turner   Reset(type, py_obj); // Use "Reset()" to ensure that py_obj is a integer type
4752c1f46dcSZachary Turner }
4762c1f46dcSZachary Turner 
477b9c1b51eSKate Stone PythonInteger::PythonInteger(int64_t value) : PythonObject() {
4782c1f46dcSZachary Turner   SetInteger(value);
4792c1f46dcSZachary Turner }
4802c1f46dcSZachary Turner 
481b9c1b51eSKate Stone PythonInteger::~PythonInteger() {}
4822c1f46dcSZachary Turner 
483b9c1b51eSKate Stone bool PythonInteger::Check(PyObject *py_obj) {
48422c8efcdSZachary Turner   if (!py_obj)
48522c8efcdSZachary Turner     return false;
48622c8efcdSZachary Turner 
48722c8efcdSZachary Turner #if PY_MAJOR_VERSION >= 3
48805097246SAdrian Prantl   // Python 3 does not have PyInt_Check.  There is only one type of integral
48905097246SAdrian Prantl   // value, long.
49022c8efcdSZachary Turner   return PyLong_Check(py_obj);
49122c8efcdSZachary Turner #else
49222c8efcdSZachary Turner   return PyLong_Check(py_obj) || PyInt_Check(py_obj);
49322c8efcdSZachary Turner #endif
4942c1f46dcSZachary Turner }
4952c1f46dcSZachary Turner 
496b9c1b51eSKate Stone void PythonInteger::Reset(PyRefType type, PyObject *py_obj) {
49705097246SAdrian Prantl   // Grab the desired reference type so that if we end up rejecting `py_obj` it
49805097246SAdrian Prantl   // still gets decremented if necessary.
499f8b22f8fSZachary Turner   PythonObject result(type, py_obj);
500f8b22f8fSZachary Turner 
501b9c1b51eSKate Stone   if (!PythonInteger::Check(py_obj)) {
502f8b22f8fSZachary Turner     PythonObject::Reset();
503f8b22f8fSZachary Turner     return;
50422c8efcdSZachary Turner   }
50522c8efcdSZachary Turner 
50622c8efcdSZachary Turner #if PY_MAJOR_VERSION < 3
50705097246SAdrian Prantl   // Always store this as a PyLong, which makes interoperability between Python
50805097246SAdrian Prantl   // 2.x and Python 3.x easier.  This is only necessary in 2.x, since 3.x
50905097246SAdrian Prantl   // doesn't even have a PyInt.
510b9c1b51eSKate Stone   if (PyInt_Check(py_obj)) {
511f8b22f8fSZachary Turner     // Since we converted the original object to a different type, the new
51205097246SAdrian Prantl     // object is an owned object regardless of the ownership semantics
51305097246SAdrian Prantl     // requested by the user.
514f8b22f8fSZachary Turner     result.Reset(PyRefType::Owned, PyLong_FromLongLong(PyInt_AsLong(py_obj)));
51522c8efcdSZachary Turner   }
51622c8efcdSZachary Turner #endif
51722c8efcdSZachary Turner 
518b9c1b51eSKate Stone   assert(PyLong_Check(result.get()) &&
519b9c1b51eSKate Stone          "Couldn't get a PyLong from this PyObject");
52022c8efcdSZachary Turner 
521b9c1b51eSKate Stone   // Calling PythonObject::Reset(const PythonObject&) will lead to stack
52205097246SAdrian Prantl   // overflow since it calls back into the virtual implementation.
523f8b22f8fSZachary Turner   PythonObject::Reset(PyRefType::Borrowed, result.get());
5242c1f46dcSZachary Turner }
5252c1f46dcSZachary Turner 
526b9c1b51eSKate Stone int64_t PythonInteger::GetInteger() const {
527b9c1b51eSKate Stone   if (m_py_obj) {
528b9c1b51eSKate Stone     assert(PyLong_Check(m_py_obj) &&
529b9c1b51eSKate Stone            "PythonInteger::GetInteger has a PyObject that isn't a PyLong");
53022c8efcdSZachary Turner 
531008ec446SGreg Clayton     int overflow = 0;
532008ec446SGreg Clayton     int64_t result = PyLong_AsLongLongAndOverflow(m_py_obj, &overflow);
533b9c1b51eSKate Stone     if (overflow != 0) {
53405097246SAdrian Prantl       // We got an integer that overflows, like 18446744072853913392L we can't
53505097246SAdrian Prantl       // use PyLong_AsLongLong() as it will return 0xffffffffffffffff. If we
53605097246SAdrian Prantl       // use the unsigned long long it will work as expected.
537008ec446SGreg Clayton       const uint64_t uval = PyLong_AsUnsignedLongLong(m_py_obj);
5384f730dc7SIlia K       result = static_cast<int64_t>(uval);
539008ec446SGreg Clayton     }
540008ec446SGreg Clayton     return result;
5412c1f46dcSZachary Turner   }
5422c1f46dcSZachary Turner   return UINT64_MAX;
5432c1f46dcSZachary Turner }
5442c1f46dcSZachary Turner 
545b9c1b51eSKate Stone void PythonInteger::SetInteger(int64_t value) {
546f8b22f8fSZachary Turner   PythonObject::Reset(PyRefType::Owned, PyLong_FromLongLong(value));
5472c1f46dcSZachary Turner }
5482c1f46dcSZachary Turner 
549b9c1b51eSKate Stone StructuredData::IntegerSP PythonInteger::CreateStructuredInteger() const {
5502c1f46dcSZachary Turner   StructuredData::IntegerSP result(new StructuredData::Integer);
5512c1f46dcSZachary Turner   result->SetValue(GetInteger());
5522c1f46dcSZachary Turner   return result;
5532c1f46dcSZachary Turner }
5542c1f46dcSZachary Turner 
555b81d715cSTatyana Krasnukha // PythonBoolean
556b81d715cSTatyana Krasnukha 
557b81d715cSTatyana Krasnukha PythonBoolean::PythonBoolean(PyRefType type, PyObject *py_obj)
558b81d715cSTatyana Krasnukha     : PythonObject() {
559b81d715cSTatyana Krasnukha   Reset(type, py_obj); // Use "Reset()" to ensure that py_obj is a boolean type
560b81d715cSTatyana Krasnukha }
561b81d715cSTatyana Krasnukha 
562b81d715cSTatyana Krasnukha PythonBoolean::PythonBoolean(bool value) {
563b81d715cSTatyana Krasnukha   SetValue(value);
564b81d715cSTatyana Krasnukha }
565b81d715cSTatyana Krasnukha 
566b81d715cSTatyana Krasnukha bool PythonBoolean::Check(PyObject *py_obj) {
567b81d715cSTatyana Krasnukha   return py_obj ? PyBool_Check(py_obj) : false;
568b81d715cSTatyana Krasnukha }
569b81d715cSTatyana Krasnukha 
570b81d715cSTatyana Krasnukha void PythonBoolean::Reset(PyRefType type, PyObject *py_obj) {
571b81d715cSTatyana Krasnukha   // Grab the desired reference type so that if we end up rejecting `py_obj` it
572b81d715cSTatyana Krasnukha   // still gets decremented if necessary.
573b81d715cSTatyana Krasnukha   PythonObject result(type, py_obj);
574b81d715cSTatyana Krasnukha 
575b81d715cSTatyana Krasnukha   if (!PythonBoolean::Check(py_obj)) {
576b81d715cSTatyana Krasnukha     PythonObject::Reset();
577b81d715cSTatyana Krasnukha     return;
578b81d715cSTatyana Krasnukha   }
579b81d715cSTatyana Krasnukha 
580b81d715cSTatyana Krasnukha   // Calling PythonObject::Reset(const PythonObject&) will lead to stack
581b81d715cSTatyana Krasnukha   // overflow since it calls back into the virtual implementation.
582b81d715cSTatyana Krasnukha   PythonObject::Reset(PyRefType::Borrowed, result.get());
583b81d715cSTatyana Krasnukha }
584b81d715cSTatyana Krasnukha 
585b81d715cSTatyana Krasnukha bool PythonBoolean::GetValue() const {
586b81d715cSTatyana Krasnukha   return m_py_obj ? PyObject_IsTrue(m_py_obj) : false;
587b81d715cSTatyana Krasnukha }
588b81d715cSTatyana Krasnukha 
589b81d715cSTatyana Krasnukha void PythonBoolean::SetValue(bool value) {
590b81d715cSTatyana Krasnukha   PythonObject::Reset(PyRefType::Owned, PyBool_FromLong(value));
591b81d715cSTatyana Krasnukha }
592b81d715cSTatyana Krasnukha 
593b81d715cSTatyana Krasnukha StructuredData::BooleanSP PythonBoolean::CreateStructuredBoolean() const {
594b81d715cSTatyana Krasnukha   StructuredData::BooleanSP result(new StructuredData::Boolean);
595b81d715cSTatyana Krasnukha   result->SetValue(GetValue());
596b81d715cSTatyana Krasnukha   return result;
597b81d715cSTatyana Krasnukha }
598b81d715cSTatyana Krasnukha 
5992c1f46dcSZachary Turner // PythonList
6002c1f46dcSZachary Turner 
601b9c1b51eSKate Stone PythonList::PythonList(PyInitialValue value) : PythonObject() {
602f8b22f8fSZachary Turner   if (value == PyInitialValue::Empty)
603f8b22f8fSZachary Turner     Reset(PyRefType::Owned, PyList_New(0));
6042c1f46dcSZachary Turner }
6052c1f46dcSZachary Turner 
606b9c1b51eSKate Stone PythonList::PythonList(int list_size) : PythonObject() {
60787f47729SZachary Turner   Reset(PyRefType::Owned, PyList_New(list_size));
60887f47729SZachary Turner }
60987f47729SZachary Turner 
610b9c1b51eSKate Stone PythonList::PythonList(PyRefType type, PyObject *py_obj) : PythonObject() {
611f8b22f8fSZachary Turner   Reset(type, py_obj); // Use "Reset()" to ensure that py_obj is a list
6122c1f46dcSZachary Turner }
6132c1f46dcSZachary Turner 
614b9c1b51eSKate Stone PythonList::~PythonList() {}
6152c1f46dcSZachary Turner 
616b9c1b51eSKate Stone bool PythonList::Check(PyObject *py_obj) {
61722c8efcdSZachary Turner   if (!py_obj)
61822c8efcdSZachary Turner     return false;
61922c8efcdSZachary Turner   return PyList_Check(py_obj);
62022c8efcdSZachary Turner }
62122c8efcdSZachary Turner 
622b9c1b51eSKate Stone void PythonList::Reset(PyRefType type, PyObject *py_obj) {
62305097246SAdrian Prantl   // Grab the desired reference type so that if we end up rejecting `py_obj` it
62405097246SAdrian Prantl   // still gets decremented if necessary.
625f8b22f8fSZachary Turner   PythonObject result(type, py_obj);
626f8b22f8fSZachary Turner 
627b9c1b51eSKate Stone   if (!PythonList::Check(py_obj)) {
628f8b22f8fSZachary Turner     PythonObject::Reset();
629f8b22f8fSZachary Turner     return;
63022c8efcdSZachary Turner   }
63122c8efcdSZachary Turner 
632b9c1b51eSKate Stone   // Calling PythonObject::Reset(const PythonObject&) will lead to stack
63305097246SAdrian Prantl   // overflow since it calls back into the virtual implementation.
634f8b22f8fSZachary Turner   PythonObject::Reset(PyRefType::Borrowed, result.get());
6352c1f46dcSZachary Turner }
6362c1f46dcSZachary Turner 
637b9c1b51eSKate Stone uint32_t PythonList::GetSize() const {
638f8b22f8fSZachary Turner   if (IsValid())
6392c1f46dcSZachary Turner     return PyList_GET_SIZE(m_py_obj);
6402c1f46dcSZachary Turner   return 0;
6412c1f46dcSZachary Turner }
6422c1f46dcSZachary Turner 
643b9c1b51eSKate Stone PythonObject PythonList::GetItemAtIndex(uint32_t index) const {
644f8b22f8fSZachary Turner   if (IsValid())
645f8b22f8fSZachary Turner     return PythonObject(PyRefType::Borrowed, PyList_GetItem(m_py_obj, index));
6462c1f46dcSZachary Turner   return PythonObject();
6472c1f46dcSZachary Turner }
6482c1f46dcSZachary Turner 
649b9c1b51eSKate Stone void PythonList::SetItemAtIndex(uint32_t index, const PythonObject &object) {
650b9c1b51eSKate Stone   if (IsAllocated() && object.IsValid()) {
651f8b22f8fSZachary Turner     // PyList_SetItem is documented to "steal" a reference, so we need to
652f8b22f8fSZachary Turner     // convert it to an owned reference by incrementing it.
653f8b22f8fSZachary Turner     Py_INCREF(object.get());
6542c1f46dcSZachary Turner     PyList_SetItem(m_py_obj, index, object.get());
6552c1f46dcSZachary Turner   }
656f8b22f8fSZachary Turner }
6572c1f46dcSZachary Turner 
658b9c1b51eSKate Stone void PythonList::AppendItem(const PythonObject &object) {
659b9c1b51eSKate Stone   if (IsAllocated() && object.IsValid()) {
660f8b22f8fSZachary Turner     // `PyList_Append` does *not* steal a reference, so do not call `Py_INCREF`
661f8b22f8fSZachary Turner     // here like we do with `PyList_SetItem`.
6622c1f46dcSZachary Turner     PyList_Append(m_py_obj, object.get());
6632c1f46dcSZachary Turner   }
664f8b22f8fSZachary Turner }
6652c1f46dcSZachary Turner 
666b9c1b51eSKate Stone StructuredData::ArraySP PythonList::CreateStructuredArray() const {
6672c1f46dcSZachary Turner   StructuredData::ArraySP result(new StructuredData::Array);
6682c1f46dcSZachary Turner   uint32_t count = GetSize();
669b9c1b51eSKate Stone   for (uint32_t i = 0; i < count; ++i) {
6702c1f46dcSZachary Turner     PythonObject obj = GetItemAtIndex(i);
6712c1f46dcSZachary Turner     result->AddItem(obj.CreateStructuredObject());
6722c1f46dcSZachary Turner   }
6732c1f46dcSZachary Turner   return result;
6742c1f46dcSZachary Turner }
6752c1f46dcSZachary Turner 
676a1405147SZachary Turner // PythonTuple
677a1405147SZachary Turner 
678b9c1b51eSKate Stone PythonTuple::PythonTuple(PyInitialValue value) : PythonObject() {
679a1405147SZachary Turner   if (value == PyInitialValue::Empty)
680a1405147SZachary Turner     Reset(PyRefType::Owned, PyTuple_New(0));
681a1405147SZachary Turner }
682a1405147SZachary Turner 
683b9c1b51eSKate Stone PythonTuple::PythonTuple(int tuple_size) : PythonObject() {
684a1405147SZachary Turner   Reset(PyRefType::Owned, PyTuple_New(tuple_size));
685a1405147SZachary Turner }
686a1405147SZachary Turner 
687b9c1b51eSKate Stone PythonTuple::PythonTuple(PyRefType type, PyObject *py_obj) : PythonObject() {
688a1405147SZachary Turner   Reset(type, py_obj); // Use "Reset()" to ensure that py_obj is a tuple
689a1405147SZachary Turner }
690a1405147SZachary Turner 
691b9c1b51eSKate Stone PythonTuple::PythonTuple(std::initializer_list<PythonObject> objects) {
692a1405147SZachary Turner   m_py_obj = PyTuple_New(objects.size());
693a1405147SZachary Turner 
694a1405147SZachary Turner   uint32_t idx = 0;
695b9c1b51eSKate Stone   for (auto object : objects) {
696a1405147SZachary Turner     if (object.IsValid())
697a1405147SZachary Turner       SetItemAtIndex(idx, object);
698a1405147SZachary Turner     idx++;
699a1405147SZachary Turner   }
700a1405147SZachary Turner }
701a1405147SZachary Turner 
702b9c1b51eSKate Stone PythonTuple::PythonTuple(std::initializer_list<PyObject *> objects) {
703a1405147SZachary Turner   m_py_obj = PyTuple_New(objects.size());
704a1405147SZachary Turner 
705a1405147SZachary Turner   uint32_t idx = 0;
706b9c1b51eSKate Stone   for (auto py_object : objects) {
707a1405147SZachary Turner     PythonObject object(PyRefType::Borrowed, py_object);
708a1405147SZachary Turner     if (object.IsValid())
709a1405147SZachary Turner       SetItemAtIndex(idx, object);
710a1405147SZachary Turner     idx++;
711a1405147SZachary Turner   }
712a1405147SZachary Turner }
713a1405147SZachary Turner 
714b9c1b51eSKate Stone PythonTuple::~PythonTuple() {}
715a1405147SZachary Turner 
716b9c1b51eSKate Stone bool PythonTuple::Check(PyObject *py_obj) {
717a1405147SZachary Turner   if (!py_obj)
718a1405147SZachary Turner     return false;
719a1405147SZachary Turner   return PyTuple_Check(py_obj);
720a1405147SZachary Turner }
721a1405147SZachary Turner 
722b9c1b51eSKate Stone void PythonTuple::Reset(PyRefType type, PyObject *py_obj) {
72305097246SAdrian Prantl   // Grab the desired reference type so that if we end up rejecting `py_obj` it
72405097246SAdrian Prantl   // still gets decremented if necessary.
725a1405147SZachary Turner   PythonObject result(type, py_obj);
726a1405147SZachary Turner 
727b9c1b51eSKate Stone   if (!PythonTuple::Check(py_obj)) {
728a1405147SZachary Turner     PythonObject::Reset();
729a1405147SZachary Turner     return;
730a1405147SZachary Turner   }
731a1405147SZachary Turner 
732b9c1b51eSKate Stone   // Calling PythonObject::Reset(const PythonObject&) will lead to stack
73305097246SAdrian Prantl   // overflow since it calls back into the virtual implementation.
734a1405147SZachary Turner   PythonObject::Reset(PyRefType::Borrowed, result.get());
735a1405147SZachary Turner }
736a1405147SZachary Turner 
737b9c1b51eSKate Stone uint32_t PythonTuple::GetSize() const {
738a1405147SZachary Turner   if (IsValid())
739a1405147SZachary Turner     return PyTuple_GET_SIZE(m_py_obj);
740a1405147SZachary Turner   return 0;
741a1405147SZachary Turner }
742a1405147SZachary Turner 
743b9c1b51eSKate Stone PythonObject PythonTuple::GetItemAtIndex(uint32_t index) const {
744a1405147SZachary Turner   if (IsValid())
745a1405147SZachary Turner     return PythonObject(PyRefType::Borrowed, PyTuple_GetItem(m_py_obj, index));
746a1405147SZachary Turner   return PythonObject();
747a1405147SZachary Turner }
748a1405147SZachary Turner 
749b9c1b51eSKate Stone void PythonTuple::SetItemAtIndex(uint32_t index, const PythonObject &object) {
750b9c1b51eSKate Stone   if (IsAllocated() && object.IsValid()) {
751a1405147SZachary Turner     // PyTuple_SetItem is documented to "steal" a reference, so we need to
752a1405147SZachary Turner     // convert it to an owned reference by incrementing it.
753a1405147SZachary Turner     Py_INCREF(object.get());
754a1405147SZachary Turner     PyTuple_SetItem(m_py_obj, index, object.get());
755a1405147SZachary Turner   }
756a1405147SZachary Turner }
757a1405147SZachary Turner 
758b9c1b51eSKate Stone StructuredData::ArraySP PythonTuple::CreateStructuredArray() const {
759a1405147SZachary Turner   StructuredData::ArraySP result(new StructuredData::Array);
760a1405147SZachary Turner   uint32_t count = GetSize();
761b9c1b51eSKate Stone   for (uint32_t i = 0; i < count; ++i) {
762a1405147SZachary Turner     PythonObject obj = GetItemAtIndex(i);
763a1405147SZachary Turner     result->AddItem(obj.CreateStructuredObject());
764a1405147SZachary Turner   }
765a1405147SZachary Turner   return result;
766a1405147SZachary Turner }
767a1405147SZachary Turner 
7682c1f46dcSZachary Turner // PythonDictionary
7692c1f46dcSZachary Turner 
770b9c1b51eSKate Stone PythonDictionary::PythonDictionary(PyInitialValue value) : PythonObject() {
771f8b22f8fSZachary Turner   if (value == PyInitialValue::Empty)
772f8b22f8fSZachary Turner     Reset(PyRefType::Owned, PyDict_New());
7732c1f46dcSZachary Turner }
7742c1f46dcSZachary Turner 
775f8b22f8fSZachary Turner PythonDictionary::PythonDictionary(PyRefType type, PyObject *py_obj)
776b9c1b51eSKate Stone     : PythonObject() {
777f8b22f8fSZachary Turner   Reset(type, py_obj); // Use "Reset()" to ensure that py_obj is a dictionary
7782c1f46dcSZachary Turner }
7792c1f46dcSZachary Turner 
780b9c1b51eSKate Stone PythonDictionary::~PythonDictionary() {}
7812c1f46dcSZachary Turner 
782b9c1b51eSKate Stone bool PythonDictionary::Check(PyObject *py_obj) {
78322c8efcdSZachary Turner   if (!py_obj)
78422c8efcdSZachary Turner     return false;
78522c8efcdSZachary Turner 
78622c8efcdSZachary Turner   return PyDict_Check(py_obj);
78722c8efcdSZachary Turner }
78822c8efcdSZachary Turner 
789b9c1b51eSKate Stone void PythonDictionary::Reset(PyRefType type, PyObject *py_obj) {
79005097246SAdrian Prantl   // Grab the desired reference type so that if we end up rejecting `py_obj` it
79105097246SAdrian Prantl   // still gets decremented if necessary.
792f8b22f8fSZachary Turner   PythonObject result(type, py_obj);
793f8b22f8fSZachary Turner 
794b9c1b51eSKate Stone   if (!PythonDictionary::Check(py_obj)) {
795f8b22f8fSZachary Turner     PythonObject::Reset();
796f8b22f8fSZachary Turner     return;
79722c8efcdSZachary Turner   }
79822c8efcdSZachary Turner 
799b9c1b51eSKate Stone   // Calling PythonObject::Reset(const PythonObject&) will lead to stack
80005097246SAdrian Prantl   // overflow since it calls back into the virtual implementation.
801f8b22f8fSZachary Turner   PythonObject::Reset(PyRefType::Borrowed, result.get());
8022c1f46dcSZachary Turner }
8032c1f46dcSZachary Turner 
804b9c1b51eSKate Stone uint32_t PythonDictionary::GetSize() const {
805f8b22f8fSZachary Turner   if (IsValid())
8062c1f46dcSZachary Turner     return PyDict_Size(m_py_obj);
8072c1f46dcSZachary Turner   return 0;
8082c1f46dcSZachary Turner }
8092c1f46dcSZachary Turner 
810b9c1b51eSKate Stone PythonList PythonDictionary::GetKeys() const {
811f8b22f8fSZachary Turner   if (IsValid())
812f8b22f8fSZachary Turner     return PythonList(PyRefType::Owned, PyDict_Keys(m_py_obj));
813f8b22f8fSZachary Turner   return PythonList(PyInitialValue::Invalid);
8142c1f46dcSZachary Turner }
8152c1f46dcSZachary Turner 
816b9c1b51eSKate Stone PythonObject PythonDictionary::GetItemForKey(const PythonObject &key) const {
817f8b22f8fSZachary Turner   if (IsAllocated() && key.IsValid())
818b9c1b51eSKate Stone     return PythonObject(PyRefType::Borrowed,
819b9c1b51eSKate Stone                         PyDict_GetItem(m_py_obj, key.get()));
8202c1f46dcSZachary Turner   return PythonObject();
8212c1f46dcSZachary Turner }
8222c1f46dcSZachary Turner 
823b9c1b51eSKate Stone void PythonDictionary::SetItemForKey(const PythonObject &key,
824b9c1b51eSKate Stone                                      const PythonObject &value) {
825f8b22f8fSZachary Turner   if (IsAllocated() && key.IsValid() && value.IsValid())
8262c1f46dcSZachary Turner     PyDict_SetItem(m_py_obj, key.get(), value.get());
8272c1f46dcSZachary Turner }
8282c1f46dcSZachary Turner 
8292c1f46dcSZachary Turner StructuredData::DictionarySP
830b9c1b51eSKate Stone PythonDictionary::CreateStructuredDictionary() const {
8312c1f46dcSZachary Turner   StructuredData::DictionarySP result(new StructuredData::Dictionary);
8322c1f46dcSZachary Turner   PythonList keys(GetKeys());
8332c1f46dcSZachary Turner   uint32_t num_keys = keys.GetSize();
834b9c1b51eSKate Stone   for (uint32_t i = 0; i < num_keys; ++i) {
8352c1f46dcSZachary Turner     PythonObject key = keys.GetItemAtIndex(i);
8362c1f46dcSZachary Turner     PythonObject value = GetItemForKey(key);
8372c1f46dcSZachary Turner     StructuredData::ObjectSP structured_value = value.CreateStructuredObject();
838f8b22f8fSZachary Turner     result->AddItem(key.Str().GetString(), structured_value);
8392c1f46dcSZachary Turner   }
8402c1f46dcSZachary Turner   return result;
8412c1f46dcSZachary Turner }
8422c1f46dcSZachary Turner 
843b9c1b51eSKate Stone PythonModule::PythonModule() : PythonObject() {}
8447841efbbSZachary Turner 
845b9c1b51eSKate Stone PythonModule::PythonModule(PyRefType type, PyObject *py_obj) {
8467841efbbSZachary Turner   Reset(type, py_obj); // Use "Reset()" to ensure that py_obj is a module
8477841efbbSZachary Turner }
8487841efbbSZachary Turner 
849b9c1b51eSKate Stone PythonModule::~PythonModule() {}
8507841efbbSZachary Turner 
851b9c1b51eSKate Stone PythonModule PythonModule::BuiltinsModule() {
852a1405147SZachary Turner #if PY_MAJOR_VERSION >= 3
853a1405147SZachary Turner   return AddModule("builtins");
854a1405147SZachary Turner #else
855a1405147SZachary Turner   return AddModule("__builtin__");
856a1405147SZachary Turner #endif
857a1405147SZachary Turner }
858a1405147SZachary Turner 
859b9c1b51eSKate Stone PythonModule PythonModule::MainModule() { return AddModule("__main__"); }
860a1405147SZachary Turner 
861b9c1b51eSKate Stone PythonModule PythonModule::AddModule(llvm::StringRef module) {
862a1405147SZachary Turner   std::string str = module.str();
863a1405147SZachary Turner   return PythonModule(PyRefType::Borrowed, PyImport_AddModule(str.c_str()));
8647841efbbSZachary Turner }
8657841efbbSZachary Turner 
866085328eeSLawrence D'Anna Expected<PythonModule> PythonModule::Import(const char *name) {
867085328eeSLawrence D'Anna   PyObject *mod = PyImport_ImportModule(name);
868085328eeSLawrence D'Anna   if (!mod)
869085328eeSLawrence D'Anna     return exception();
870085328eeSLawrence D'Anna   return Take<PythonModule>(mod);
871085328eeSLawrence D'Anna }
872085328eeSLawrence D'Anna 
873085328eeSLawrence D'Anna Expected<PythonObject> PythonModule::Get(const char *name) {
874085328eeSLawrence D'Anna   if (!IsValid())
875085328eeSLawrence D'Anna     return nullDeref();
876085328eeSLawrence D'Anna   PyObject *dict = PyModule_GetDict(m_py_obj);
877085328eeSLawrence D'Anna   if (!dict)
878085328eeSLawrence D'Anna     return exception();
879085328eeSLawrence D'Anna   PyObject *item = PyDict_GetItemString(dict, name);
880085328eeSLawrence D'Anna   if (!item)
881085328eeSLawrence D'Anna     return exception();
882085328eeSLawrence D'Anna   return Retain<PythonObject>(item);
8832419f1d5SZachary Turner }
8842419f1d5SZachary Turner 
885b9c1b51eSKate Stone bool PythonModule::Check(PyObject *py_obj) {
8867841efbbSZachary Turner   if (!py_obj)
8877841efbbSZachary Turner     return false;
8887841efbbSZachary Turner 
8897841efbbSZachary Turner   return PyModule_Check(py_obj);
8907841efbbSZachary Turner }
8917841efbbSZachary Turner 
892b9c1b51eSKate Stone void PythonModule::Reset(PyRefType type, PyObject *py_obj) {
89305097246SAdrian Prantl   // Grab the desired reference type so that if we end up rejecting `py_obj` it
89405097246SAdrian Prantl   // still gets decremented if necessary.
8957841efbbSZachary Turner   PythonObject result(type, py_obj);
8967841efbbSZachary Turner 
897b9c1b51eSKate Stone   if (!PythonModule::Check(py_obj)) {
8987841efbbSZachary Turner     PythonObject::Reset();
8997841efbbSZachary Turner     return;
9007841efbbSZachary Turner   }
9017841efbbSZachary Turner 
902b9c1b51eSKate Stone   // Calling PythonObject::Reset(const PythonObject&) will lead to stack
90305097246SAdrian Prantl   // overflow since it calls back into the virtual implementation.
9047841efbbSZachary Turner   PythonObject::Reset(PyRefType::Borrowed, result.get());
9057841efbbSZachary Turner }
9067841efbbSZachary Turner 
907b9c1b51eSKate Stone PythonDictionary PythonModule::GetDictionary() const {
9087841efbbSZachary Turner   return PythonDictionary(PyRefType::Borrowed, PyModule_GetDict(m_py_obj));
9097841efbbSZachary Turner }
9107841efbbSZachary Turner 
911b9c1b51eSKate Stone PythonCallable::PythonCallable() : PythonObject() {}
912a1405147SZachary Turner 
913b9c1b51eSKate Stone PythonCallable::PythonCallable(PyRefType type, PyObject *py_obj) {
914a1405147SZachary Turner   Reset(type, py_obj); // Use "Reset()" to ensure that py_obj is a callable
915a1405147SZachary Turner }
916a1405147SZachary Turner 
917b9c1b51eSKate Stone PythonCallable::~PythonCallable() {}
918a1405147SZachary Turner 
919b9c1b51eSKate Stone bool PythonCallable::Check(PyObject *py_obj) {
920a1405147SZachary Turner   if (!py_obj)
921a1405147SZachary Turner     return false;
922a1405147SZachary Turner 
923a1405147SZachary Turner   return PyCallable_Check(py_obj);
924a1405147SZachary Turner }
925a1405147SZachary Turner 
926b9c1b51eSKate Stone void PythonCallable::Reset(PyRefType type, PyObject *py_obj) {
92705097246SAdrian Prantl   // Grab the desired reference type so that if we end up rejecting `py_obj` it
92805097246SAdrian Prantl   // still gets decremented if necessary.
929a1405147SZachary Turner   PythonObject result(type, py_obj);
930a1405147SZachary Turner 
931b9c1b51eSKate Stone   if (!PythonCallable::Check(py_obj)) {
932a1405147SZachary Turner     PythonObject::Reset();
933a1405147SZachary Turner     return;
934a1405147SZachary Turner   }
935a1405147SZachary Turner 
936b9c1b51eSKate Stone   // Calling PythonObject::Reset(const PythonObject&) will lead to stack
93705097246SAdrian Prantl   // overflow since it calls back into the virtual implementation.
938a1405147SZachary Turner   PythonObject::Reset(PyRefType::Borrowed, result.get());
939a1405147SZachary Turner }
940a1405147SZachary Turner 
94127a14f19SJim Ingham PythonCallable::ArgInfo PythonCallable::GetNumInitArguments() const {
94227a14f19SJim Ingham   ArgInfo result = {0, false, false, false};
94327a14f19SJim Ingham   if (!IsValid())
94427a14f19SJim Ingham     return result;
94527a14f19SJim Ingham 
94627a14f19SJim Ingham   PythonObject __init__ = GetAttributeValue("__init__");
94727a14f19SJim Ingham   if (__init__.IsValid() ) {
94827a14f19SJim Ingham     auto __init_callable__ = __init__.AsType<PythonCallable>();
94927a14f19SJim Ingham     if (__init_callable__.IsValid())
95027a14f19SJim Ingham       return __init_callable__.GetNumArguments();
95127a14f19SJim Ingham   }
95227a14f19SJim Ingham   return result;
95327a14f19SJim Ingham }
95427a14f19SJim Ingham 
955b9c1b51eSKate Stone PythonCallable::ArgInfo PythonCallable::GetNumArguments() const {
956a5d6765cSEnrico Granata   ArgInfo result = {0, false, false, false};
957a1405147SZachary Turner   if (!IsValid())
958b58fb2f4SZachary Turner     return result;
959a1405147SZachary Turner 
960a1405147SZachary Turner   PyObject *py_func_obj = m_py_obj;
961b9c1b51eSKate Stone   if (PyMethod_Check(py_func_obj)) {
962a1405147SZachary Turner     py_func_obj = PyMethod_GET_FUNCTION(py_func_obj);
963a5d6765cSEnrico Granata     PythonObject im_self = GetAttributeValue("im_self");
964a5d6765cSEnrico Granata     if (im_self.IsValid() && !im_self.IsNone())
965a5d6765cSEnrico Granata       result.is_bound_method = true;
966b9c1b51eSKate Stone   } else {
967a5d6765cSEnrico Granata     // see if this is a callable object with an __call__ method
968b9c1b51eSKate Stone     if (!PyFunction_Check(py_func_obj)) {
969a5d6765cSEnrico Granata       PythonObject __call__ = GetAttributeValue("__call__");
970b9c1b51eSKate Stone       if (__call__.IsValid()) {
971a5d6765cSEnrico Granata         auto __callable__ = __call__.AsType<PythonCallable>();
972b9c1b51eSKate Stone         if (__callable__.IsValid()) {
973a5d6765cSEnrico Granata           py_func_obj = PyMethod_GET_FUNCTION(__callable__.get());
974a5d6765cSEnrico Granata           PythonObject im_self = GetAttributeValue("im_self");
975a5d6765cSEnrico Granata           if (im_self.IsValid() && !im_self.IsNone())
976a5d6765cSEnrico Granata             result.is_bound_method = true;
977a5d6765cSEnrico Granata         }
978a5d6765cSEnrico Granata       }
979a5d6765cSEnrico Granata     }
980a5d6765cSEnrico Granata   }
981a1405147SZachary Turner 
982a1405147SZachary Turner   if (!py_func_obj)
983b58fb2f4SZachary Turner     return result;
984a1405147SZachary Turner 
985a1405147SZachary Turner   PyCodeObject *code = (PyCodeObject *)PyFunction_GET_CODE(py_func_obj);
986a1405147SZachary Turner   if (!code)
987b58fb2f4SZachary Turner     return result;
988a1405147SZachary Turner 
989b58fb2f4SZachary Turner   result.count = code->co_argcount;
990b58fb2f4SZachary Turner   result.has_varargs = !!(code->co_flags & CO_VARARGS);
991b58fb2f4SZachary Turner   result.has_kwargs = !!(code->co_flags & CO_VARKEYWORDS);
992b58fb2f4SZachary Turner   return result;
993b58fb2f4SZachary Turner }
994b58fb2f4SZachary Turner 
995b9c1b51eSKate Stone PythonObject PythonCallable::operator()() {
996b9c1b51eSKate Stone   return PythonObject(PyRefType::Owned, PyObject_CallObject(m_py_obj, nullptr));
997a1405147SZachary Turner }
998a1405147SZachary Turner 
999b9c1b51eSKate Stone PythonObject PythonCallable::
1000b9c1b51eSKate Stone operator()(std::initializer_list<PyObject *> args) {
1001a1405147SZachary Turner   PythonTuple arg_tuple(args);
1002a1405147SZachary Turner   return PythonObject(PyRefType::Owned,
1003a1405147SZachary Turner                       PyObject_CallObject(m_py_obj, arg_tuple.get()));
1004a1405147SZachary Turner }
1005a1405147SZachary Turner 
1006b9c1b51eSKate Stone PythonObject PythonCallable::
1007b9c1b51eSKate Stone operator()(std::initializer_list<PythonObject> args) {
1008a1405147SZachary Turner   PythonTuple arg_tuple(args);
1009a1405147SZachary Turner   return PythonObject(PyRefType::Owned,
1010a1405147SZachary Turner                       PyObject_CallObject(m_py_obj, arg_tuple.get()));
1011a1405147SZachary Turner }
1012a1405147SZachary Turner 
1013b9c1b51eSKate Stone PythonFile::PythonFile() : PythonObject() {}
101432064024SZachary Turner 
1015b9c1b51eSKate Stone PythonFile::PythonFile(File &file, const char *mode) { Reset(file, mode); }
10169c40264fSZachary Turner 
1017b9c1b51eSKate Stone PythonFile::PythonFile(PyRefType type, PyObject *o) { Reset(type, o); }
10189c40264fSZachary Turner 
1019b9c1b51eSKate Stone PythonFile::~PythonFile() {}
10209c40264fSZachary Turner 
1021b9c1b51eSKate Stone bool PythonFile::Check(PyObject *py_obj) {
102296898eb6SLawrence D'Anna   if (!py_obj)
102396898eb6SLawrence D'Anna     return false;
10249c40264fSZachary Turner #if PY_MAJOR_VERSION < 3
102523502721SJason Molenda   return PyFile_Check(py_obj);
102623502721SJason Molenda #else
10279c40264fSZachary Turner   // In Python 3, there is no `PyFile_Check`, and in fact PyFile is not even a
10289c40264fSZachary Turner   // first-class object type anymore.  `PyFile_FromFd` is just a thin wrapper
102905097246SAdrian Prantl   // over `io.open()`, which returns some object derived from `io.IOBase`. As a
103005097246SAdrian Prantl   // result, the only way to detect a file in Python 3 is to check whether it
1031*21b8a8aeSLawrence D'Anna   // inherits from `io.IOBase`.
1032*21b8a8aeSLawrence D'Anna   auto io_module = PythonModule::Import("io");
1033*21b8a8aeSLawrence D'Anna   if (!io_module) {
1034*21b8a8aeSLawrence D'Anna     llvm::consumeError(io_module.takeError());
10359c40264fSZachary Turner     return false;
1036*21b8a8aeSLawrence D'Anna   }
1037*21b8a8aeSLawrence D'Anna   auto iobase = io_module.get().Get("IOBase");
1038*21b8a8aeSLawrence D'Anna   if (!iobase) {
1039*21b8a8aeSLawrence D'Anna     llvm::consumeError(iobase.takeError());
10409c40264fSZachary Turner     return false;
1041*21b8a8aeSLawrence D'Anna   }
1042*21b8a8aeSLawrence D'Anna   int r = PyObject_IsInstance(py_obj, iobase.get().get());
1043*21b8a8aeSLawrence D'Anna   if (r < 0) {
1044*21b8a8aeSLawrence D'Anna     llvm::consumeError(exception()); // clear the exception and log it.
1045*21b8a8aeSLawrence D'Anna     return false;
1046*21b8a8aeSLawrence D'Anna   }
1047*21b8a8aeSLawrence D'Anna   return !!r;
104823502721SJason Molenda #endif
10499c40264fSZachary Turner }
10509c40264fSZachary Turner 
1051b9c1b51eSKate Stone void PythonFile::Reset(PyRefType type, PyObject *py_obj) {
105205097246SAdrian Prantl   // Grab the desired reference type so that if we end up rejecting `py_obj` it
105305097246SAdrian Prantl   // still gets decremented if necessary.
10549c40264fSZachary Turner   PythonObject result(type, py_obj);
10559c40264fSZachary Turner 
105623502721SJason Molenda   if (!PythonFile::Check(py_obj)) {
10579c40264fSZachary Turner     PythonObject::Reset();
10589c40264fSZachary Turner     return;
10599c40264fSZachary Turner   }
10609c40264fSZachary Turner 
10619c40264fSZachary Turner   // Calling PythonObject::Reset(const PythonObject&) will lead to stack
10629c40264fSZachary Turner   // overflow since it calls back into the virtual implementation.
10639c40264fSZachary Turner   PythonObject::Reset(PyRefType::Borrowed, result.get());
10649c40264fSZachary Turner }
10659c40264fSZachary Turner 
1066b9c1b51eSKate Stone void PythonFile::Reset(File &file, const char *mode) {
1067b9c1b51eSKate Stone   if (!file.IsValid()) {
106832ac147bSZachary Turner     Reset();
106932ac147bSZachary Turner     return;
107032ac147bSZachary Turner   }
107132ac147bSZachary Turner 
10729c40264fSZachary Turner   char *cmode = const_cast<char *>(mode);
10739c40264fSZachary Turner #if PY_MAJOR_VERSION >= 3
1074b9c1b51eSKate Stone   Reset(PyRefType::Owned, PyFile_FromFd(file.GetDescriptor(), nullptr, cmode,
1075b9c1b51eSKate Stone                                         -1, nullptr, "ignore", nullptr, 0));
10769c40264fSZachary Turner #else
10779c40264fSZachary Turner   // Read through the Python source, doesn't seem to modify these strings
10789c40264fSZachary Turner   Reset(PyRefType::Owned,
1079b9c1b51eSKate Stone         PyFile_FromFile(file.GetStream(), const_cast<char *>(""), cmode,
1080b9c1b51eSKate Stone                         nullptr));
10819c40264fSZachary Turner #endif
10829c40264fSZachary Turner }
10839c40264fSZachary Turner 
1084744959b9SEnrico Granata 
10852fce1137SLawrence D'Anna FileUP PythonFile::GetUnderlyingFile() const {
1086eda01c31SZachary Turner   if (!IsValid())
10872fce1137SLawrence D'Anna     return nullptr;
1088eda01c31SZachary Turner 
1089eda01c31SZachary Turner   // We don't own the file descriptor returned by this function, make sure the
1090eda01c31SZachary Turner   // File object knows about that.
1091744959b9SEnrico Granata   PythonString py_mode = GetAttributeValue("mode").AsType<PythonString>();
109257504530SLawrence D'Anna   auto options = File::GetOptionsFromMode(py_mode.GetString());
1093f913fd6eSLawrence D'Anna   auto file = std::unique_ptr<File>(
1094f913fd6eSLawrence D'Anna       new NativeFile(PyObject_AsFileDescriptor(m_py_obj), options, false));
10952fce1137SLawrence D'Anna   if (!file->IsValid())
10962fce1137SLawrence D'Anna     return nullptr;
10972fce1137SLawrence D'Anna   return file;
1098eda01c31SZachary Turner }
1099d68983e3SPavel Labath 
1100*21b8a8aeSLawrence D'Anna namespace {
1101*21b8a8aeSLawrence D'Anna class GIL {
1102*21b8a8aeSLawrence D'Anna public:
1103*21b8a8aeSLawrence D'Anna   GIL() {
1104*21b8a8aeSLawrence D'Anna     m_state = PyGILState_Ensure();
1105*21b8a8aeSLawrence D'Anna     assert(!PyErr_Occurred());
1106*21b8a8aeSLawrence D'Anna   }
1107*21b8a8aeSLawrence D'Anna   ~GIL() { PyGILState_Release(m_state); }
1108*21b8a8aeSLawrence D'Anna 
1109*21b8a8aeSLawrence D'Anna protected:
1110*21b8a8aeSLawrence D'Anna   PyGILState_STATE m_state;
1111*21b8a8aeSLawrence D'Anna };
1112*21b8a8aeSLawrence D'Anna } // namespace
1113*21b8a8aeSLawrence D'Anna 
1114085328eeSLawrence D'Anna const char *PythonException::toCString() const {
1115085328eeSLawrence D'Anna   if (!m_repr_bytes)
1116085328eeSLawrence D'Anna     return "unknown exception";
1117085328eeSLawrence D'Anna   return PyBytes_AS_STRING(m_repr_bytes);
1118085328eeSLawrence D'Anna }
1119085328eeSLawrence D'Anna 
1120085328eeSLawrence D'Anna PythonException::PythonException(const char *caller) {
1121085328eeSLawrence D'Anna   assert(PyErr_Occurred());
1122085328eeSLawrence D'Anna   m_exception_type = m_exception = m_traceback = m_repr_bytes = NULL;
1123085328eeSLawrence D'Anna   PyErr_Fetch(&m_exception_type, &m_exception, &m_traceback);
1124085328eeSLawrence D'Anna   PyErr_NormalizeException(&m_exception_type, &m_exception, &m_traceback);
1125085328eeSLawrence D'Anna   PyErr_Clear();
1126085328eeSLawrence D'Anna   if (m_exception) {
1127085328eeSLawrence D'Anna     PyObject *repr = PyObject_Repr(m_exception);
1128085328eeSLawrence D'Anna     if (repr) {
1129085328eeSLawrence D'Anna       m_repr_bytes = PyUnicode_AsEncodedString(repr, "utf-8", nullptr);
1130085328eeSLawrence D'Anna       if (!m_repr_bytes) {
1131085328eeSLawrence D'Anna         PyErr_Clear();
1132085328eeSLawrence D'Anna       }
1133085328eeSLawrence D'Anna       Py_XDECREF(repr);
1134085328eeSLawrence D'Anna     } else {
1135085328eeSLawrence D'Anna       PyErr_Clear();
1136085328eeSLawrence D'Anna     }
1137085328eeSLawrence D'Anna   }
1138085328eeSLawrence D'Anna   Log *log = GetLogIfAllCategoriesSet(LIBLLDB_LOG_SCRIPT);
1139085328eeSLawrence D'Anna   if (caller)
1140085328eeSLawrence D'Anna     LLDB_LOGF(log, "%s failed with exception: %s", caller, toCString());
1141085328eeSLawrence D'Anna   else
1142085328eeSLawrence D'Anna     LLDB_LOGF(log, "python exception: %s", toCString());
1143085328eeSLawrence D'Anna }
1144085328eeSLawrence D'Anna void PythonException::Restore() {
1145085328eeSLawrence D'Anna   if (m_exception_type && m_exception) {
1146085328eeSLawrence D'Anna     PyErr_Restore(m_exception_type, m_exception, m_traceback);
1147085328eeSLawrence D'Anna   } else {
1148085328eeSLawrence D'Anna     PyErr_SetString(PyExc_Exception, toCString());
1149085328eeSLawrence D'Anna   }
1150085328eeSLawrence D'Anna   m_exception_type = m_exception = m_traceback = NULL;
1151085328eeSLawrence D'Anna }
1152085328eeSLawrence D'Anna 
1153085328eeSLawrence D'Anna PythonException::~PythonException() {
1154085328eeSLawrence D'Anna   Py_XDECREF(m_exception_type);
1155085328eeSLawrence D'Anna   Py_XDECREF(m_exception);
1156085328eeSLawrence D'Anna   Py_XDECREF(m_traceback);
1157085328eeSLawrence D'Anna   Py_XDECREF(m_repr_bytes);
1158085328eeSLawrence D'Anna }
1159085328eeSLawrence D'Anna 
1160085328eeSLawrence D'Anna void PythonException::log(llvm::raw_ostream &OS) const { OS << toCString(); }
1161085328eeSLawrence D'Anna 
1162085328eeSLawrence D'Anna std::error_code PythonException::convertToErrorCode() const {
1163085328eeSLawrence D'Anna   return llvm::inconvertibleErrorCode();
1164085328eeSLawrence D'Anna }
1165085328eeSLawrence D'Anna 
1166085328eeSLawrence D'Anna char PythonException::ID = 0;
1167085328eeSLawrence D'Anna 
1168*21b8a8aeSLawrence D'Anna llvm::Expected<uint32_t> GetOptionsForPyObject(const PythonObject &obj) {
1169*21b8a8aeSLawrence D'Anna   uint32_t options = 0;
1170*21b8a8aeSLawrence D'Anna #if PY_MAJOR_VERSION >= 3
1171*21b8a8aeSLawrence D'Anna   auto readable = As<bool>(obj.CallMethod("readable"));
1172*21b8a8aeSLawrence D'Anna   if (!readable)
1173*21b8a8aeSLawrence D'Anna     return readable.takeError();
1174*21b8a8aeSLawrence D'Anna   auto writable = As<bool>(obj.CallMethod("writable"));
1175*21b8a8aeSLawrence D'Anna   if (!writable)
1176*21b8a8aeSLawrence D'Anna     return writable.takeError();
1177*21b8a8aeSLawrence D'Anna   if (readable.get())
1178*21b8a8aeSLawrence D'Anna     options |= File::eOpenOptionRead;
1179*21b8a8aeSLawrence D'Anna   if (writable.get())
1180*21b8a8aeSLawrence D'Anna     options |= File::eOpenOptionWrite;
1181*21b8a8aeSLawrence D'Anna #else
1182*21b8a8aeSLawrence D'Anna   PythonString py_mode = obj.GetAttributeValue("mode").AsType<PythonString>();
1183*21b8a8aeSLawrence D'Anna   options = File::GetOptionsFromMode(py_mode.GetString());
1184*21b8a8aeSLawrence D'Anna #endif
1185*21b8a8aeSLawrence D'Anna   return options;
1186*21b8a8aeSLawrence D'Anna }
1187*21b8a8aeSLawrence D'Anna 
1188*21b8a8aeSLawrence D'Anna // Base class template for python files.   All it knows how to do
1189*21b8a8aeSLawrence D'Anna // is hold a reference to the python object and close or flush it
1190*21b8a8aeSLawrence D'Anna // when the File is closed.
1191*21b8a8aeSLawrence D'Anna namespace {
1192*21b8a8aeSLawrence D'Anna template <typename Base> class OwnedPythonFile : public Base {
1193*21b8a8aeSLawrence D'Anna public:
1194*21b8a8aeSLawrence D'Anna   template <typename... Args>
1195*21b8a8aeSLawrence D'Anna   OwnedPythonFile(const PythonFile &file, bool borrowed, Args... args)
1196*21b8a8aeSLawrence D'Anna       : Base(args...), m_py_obj(file), m_borrowed(borrowed) {
1197*21b8a8aeSLawrence D'Anna     assert(m_py_obj);
1198*21b8a8aeSLawrence D'Anna   }
1199*21b8a8aeSLawrence D'Anna 
1200*21b8a8aeSLawrence D'Anna   ~OwnedPythonFile() override {
1201*21b8a8aeSLawrence D'Anna     assert(m_py_obj);
1202*21b8a8aeSLawrence D'Anna     GIL takeGIL;
1203*21b8a8aeSLawrence D'Anna     Close();
1204*21b8a8aeSLawrence D'Anna     m_py_obj.Reset();
1205*21b8a8aeSLawrence D'Anna   }
1206*21b8a8aeSLawrence D'Anna 
1207*21b8a8aeSLawrence D'Anna   bool IsPythonSideValid() const {
1208*21b8a8aeSLawrence D'Anna     GIL takeGIL;
1209*21b8a8aeSLawrence D'Anna     auto closed = As<bool>(m_py_obj.GetAttribute("closed"));
1210*21b8a8aeSLawrence D'Anna     if (!closed) {
1211*21b8a8aeSLawrence D'Anna       llvm::consumeError(closed.takeError());
1212*21b8a8aeSLawrence D'Anna       return false;
1213*21b8a8aeSLawrence D'Anna     }
1214*21b8a8aeSLawrence D'Anna     return !closed.get();
1215*21b8a8aeSLawrence D'Anna   }
1216*21b8a8aeSLawrence D'Anna 
1217*21b8a8aeSLawrence D'Anna   bool IsValid() const override {
1218*21b8a8aeSLawrence D'Anna     return IsPythonSideValid() && Base::IsValid();
1219*21b8a8aeSLawrence D'Anna   }
1220*21b8a8aeSLawrence D'Anna 
1221*21b8a8aeSLawrence D'Anna   Status Close() override {
1222*21b8a8aeSLawrence D'Anna     assert(m_py_obj);
1223*21b8a8aeSLawrence D'Anna     Status py_error, base_error;
1224*21b8a8aeSLawrence D'Anna     GIL takeGIL;
1225*21b8a8aeSLawrence D'Anna     if (!m_borrowed) {
1226*21b8a8aeSLawrence D'Anna       auto r = m_py_obj.CallMethod("close");
1227*21b8a8aeSLawrence D'Anna       if (!r)
1228*21b8a8aeSLawrence D'Anna         py_error = Status(r.takeError());
1229*21b8a8aeSLawrence D'Anna     }
1230*21b8a8aeSLawrence D'Anna     base_error = Base::Close();
1231*21b8a8aeSLawrence D'Anna     if (py_error.Fail())
1232*21b8a8aeSLawrence D'Anna       return py_error;
1233*21b8a8aeSLawrence D'Anna     return base_error;
1234*21b8a8aeSLawrence D'Anna   };
1235*21b8a8aeSLawrence D'Anna 
1236*21b8a8aeSLawrence D'Anna protected:
1237*21b8a8aeSLawrence D'Anna   PythonFile m_py_obj;
1238*21b8a8aeSLawrence D'Anna   bool m_borrowed;
1239*21b8a8aeSLawrence D'Anna };
1240*21b8a8aeSLawrence D'Anna } // namespace
1241*21b8a8aeSLawrence D'Anna 
1242*21b8a8aeSLawrence D'Anna // A SimplePythonFile is a OwnedPythonFile that just does all I/O as
1243*21b8a8aeSLawrence D'Anna // a NativeFile
1244*21b8a8aeSLawrence D'Anna namespace {
1245*21b8a8aeSLawrence D'Anna class SimplePythonFile : public OwnedPythonFile<NativeFile> {
1246*21b8a8aeSLawrence D'Anna public:
1247*21b8a8aeSLawrence D'Anna   SimplePythonFile(const PythonFile &file, bool borrowed, int fd,
1248*21b8a8aeSLawrence D'Anna                    uint32_t options)
1249*21b8a8aeSLawrence D'Anna       : OwnedPythonFile(file, borrowed, fd, options, false) {}
1250*21b8a8aeSLawrence D'Anna };
1251*21b8a8aeSLawrence D'Anna } // namespace
1252*21b8a8aeSLawrence D'Anna 
1253*21b8a8aeSLawrence D'Anna #if PY_MAJOR_VERSION >= 3
1254*21b8a8aeSLawrence D'Anna 
1255*21b8a8aeSLawrence D'Anna namespace {
1256*21b8a8aeSLawrence D'Anna class PythonBuffer {
1257*21b8a8aeSLawrence D'Anna public:
1258*21b8a8aeSLawrence D'Anna   PythonBuffer &operator=(const PythonBuffer &) = delete;
1259*21b8a8aeSLawrence D'Anna   PythonBuffer(const PythonBuffer &) = delete;
1260*21b8a8aeSLawrence D'Anna 
1261*21b8a8aeSLawrence D'Anna   static Expected<PythonBuffer> Create(PythonObject &obj,
1262*21b8a8aeSLawrence D'Anna                                        int flags = PyBUF_SIMPLE) {
1263*21b8a8aeSLawrence D'Anna     Py_buffer py_buffer = {};
1264*21b8a8aeSLawrence D'Anna     PyObject_GetBuffer(obj.get(), &py_buffer, flags);
1265*21b8a8aeSLawrence D'Anna     if (!py_buffer.obj)
1266*21b8a8aeSLawrence D'Anna       return llvm::make_error<PythonException>();
1267*21b8a8aeSLawrence D'Anna     return PythonBuffer(py_buffer);
1268*21b8a8aeSLawrence D'Anna   }
1269*21b8a8aeSLawrence D'Anna 
1270*21b8a8aeSLawrence D'Anna   PythonBuffer(PythonBuffer &&other) {
1271*21b8a8aeSLawrence D'Anna     m_buffer = other.m_buffer;
1272*21b8a8aeSLawrence D'Anna     other.m_buffer.obj = nullptr;
1273*21b8a8aeSLawrence D'Anna   }
1274*21b8a8aeSLawrence D'Anna 
1275*21b8a8aeSLawrence D'Anna   ~PythonBuffer() {
1276*21b8a8aeSLawrence D'Anna     if (m_buffer.obj)
1277*21b8a8aeSLawrence D'Anna       PyBuffer_Release(&m_buffer);
1278*21b8a8aeSLawrence D'Anna   }
1279*21b8a8aeSLawrence D'Anna 
1280*21b8a8aeSLawrence D'Anna   Py_buffer &get() { return m_buffer; }
1281*21b8a8aeSLawrence D'Anna 
1282*21b8a8aeSLawrence D'Anna private:
1283*21b8a8aeSLawrence D'Anna   // takes ownership of the buffer.
1284*21b8a8aeSLawrence D'Anna   PythonBuffer(const Py_buffer &py_buffer) : m_buffer(py_buffer) {}
1285*21b8a8aeSLawrence D'Anna   Py_buffer m_buffer;
1286*21b8a8aeSLawrence D'Anna };
1287*21b8a8aeSLawrence D'Anna } // namespace
1288*21b8a8aeSLawrence D'Anna 
1289*21b8a8aeSLawrence D'Anna // Shared methods between TextPythonFile and BinaryPythonFile
1290*21b8a8aeSLawrence D'Anna namespace {
1291*21b8a8aeSLawrence D'Anna class PythonIOFile : public OwnedPythonFile<File> {
1292*21b8a8aeSLawrence D'Anna public:
1293*21b8a8aeSLawrence D'Anna   PythonIOFile(const PythonFile &file, bool borrowed)
1294*21b8a8aeSLawrence D'Anna       : OwnedPythonFile(file, borrowed) {}
1295*21b8a8aeSLawrence D'Anna 
1296*21b8a8aeSLawrence D'Anna   ~PythonIOFile() override { Close(); }
1297*21b8a8aeSLawrence D'Anna 
1298*21b8a8aeSLawrence D'Anna   bool IsValid() const override { return IsPythonSideValid(); }
1299*21b8a8aeSLawrence D'Anna 
1300*21b8a8aeSLawrence D'Anna   Status Close() override {
1301*21b8a8aeSLawrence D'Anna     assert(m_py_obj);
1302*21b8a8aeSLawrence D'Anna     GIL takeGIL;
1303*21b8a8aeSLawrence D'Anna     if (m_borrowed)
1304*21b8a8aeSLawrence D'Anna       return Flush();
1305*21b8a8aeSLawrence D'Anna     auto r = m_py_obj.CallMethod("close");
1306*21b8a8aeSLawrence D'Anna     if (!r)
1307*21b8a8aeSLawrence D'Anna       return Status(r.takeError());
1308*21b8a8aeSLawrence D'Anna     return Status();
1309*21b8a8aeSLawrence D'Anna   }
1310*21b8a8aeSLawrence D'Anna 
1311*21b8a8aeSLawrence D'Anna   Status Flush() override {
1312*21b8a8aeSLawrence D'Anna     GIL takeGIL;
1313*21b8a8aeSLawrence D'Anna     auto r = m_py_obj.CallMethod("flush");
1314*21b8a8aeSLawrence D'Anna     if (!r)
1315*21b8a8aeSLawrence D'Anna       return Status(r.takeError());
1316*21b8a8aeSLawrence D'Anna     return Status();
1317*21b8a8aeSLawrence D'Anna   }
1318*21b8a8aeSLawrence D'Anna 
1319*21b8a8aeSLawrence D'Anna };
1320*21b8a8aeSLawrence D'Anna } // namespace
1321*21b8a8aeSLawrence D'Anna 
1322*21b8a8aeSLawrence D'Anna namespace {
1323*21b8a8aeSLawrence D'Anna class BinaryPythonFile : public PythonIOFile {
1324*21b8a8aeSLawrence D'Anna protected:
1325*21b8a8aeSLawrence D'Anna   int m_descriptor;
1326*21b8a8aeSLawrence D'Anna 
1327*21b8a8aeSLawrence D'Anna public:
1328*21b8a8aeSLawrence D'Anna   BinaryPythonFile(int fd, const PythonFile &file, bool borrowed)
1329*21b8a8aeSLawrence D'Anna       : PythonIOFile(file, borrowed),
1330*21b8a8aeSLawrence D'Anna         m_descriptor(File::DescriptorIsValid(fd) ? fd
1331*21b8a8aeSLawrence D'Anna                                                  : File::kInvalidDescriptor) {}
1332*21b8a8aeSLawrence D'Anna 
1333*21b8a8aeSLawrence D'Anna   int GetDescriptor() const override { return m_descriptor; }
1334*21b8a8aeSLawrence D'Anna 
1335*21b8a8aeSLawrence D'Anna   Status Write(const void *buf, size_t &num_bytes) override {
1336*21b8a8aeSLawrence D'Anna     GIL takeGIL;
1337*21b8a8aeSLawrence D'Anna     PyObject *pybuffer_p = PyMemoryView_FromMemory(
1338*21b8a8aeSLawrence D'Anna         const_cast<char *>((const char *)buf), num_bytes, PyBUF_READ);
1339*21b8a8aeSLawrence D'Anna     if (!pybuffer_p)
1340*21b8a8aeSLawrence D'Anna       return Status(llvm::make_error<PythonException>());
1341*21b8a8aeSLawrence D'Anna     auto pybuffer = Take<PythonObject>(pybuffer_p);
1342*21b8a8aeSLawrence D'Anna     num_bytes = 0;
1343*21b8a8aeSLawrence D'Anna     auto bytes_written = As<long long>(m_py_obj.CallMethod("write", pybuffer));
1344*21b8a8aeSLawrence D'Anna     if (!bytes_written)
1345*21b8a8aeSLawrence D'Anna       return Status(bytes_written.takeError());
1346*21b8a8aeSLawrence D'Anna     if (bytes_written.get() < 0)
1347*21b8a8aeSLawrence D'Anna       return Status(".write() method returned a negative number!");
1348*21b8a8aeSLawrence D'Anna     static_assert(sizeof(long long) >= sizeof(size_t), "overflow");
1349*21b8a8aeSLawrence D'Anna     num_bytes = bytes_written.get();
1350*21b8a8aeSLawrence D'Anna     return Status();
1351*21b8a8aeSLawrence D'Anna   }
1352*21b8a8aeSLawrence D'Anna 
1353*21b8a8aeSLawrence D'Anna   Status Read(void *buf, size_t &num_bytes) override {
1354*21b8a8aeSLawrence D'Anna     GIL takeGIL;
1355*21b8a8aeSLawrence D'Anna     static_assert(sizeof(long long) >= sizeof(size_t), "overflow");
1356*21b8a8aeSLawrence D'Anna     auto pybuffer_obj =
1357*21b8a8aeSLawrence D'Anna         m_py_obj.CallMethod("read", (unsigned long long)num_bytes);
1358*21b8a8aeSLawrence D'Anna     if (!pybuffer_obj)
1359*21b8a8aeSLawrence D'Anna       return Status(pybuffer_obj.takeError());
1360*21b8a8aeSLawrence D'Anna     num_bytes = 0;
1361*21b8a8aeSLawrence D'Anna     if (pybuffer_obj.get().IsNone()) {
1362*21b8a8aeSLawrence D'Anna       // EOF
1363*21b8a8aeSLawrence D'Anna       num_bytes = 0;
1364*21b8a8aeSLawrence D'Anna       return Status();
1365*21b8a8aeSLawrence D'Anna     }
1366*21b8a8aeSLawrence D'Anna     auto pybuffer = PythonBuffer::Create(pybuffer_obj.get());
1367*21b8a8aeSLawrence D'Anna     if (!pybuffer)
1368*21b8a8aeSLawrence D'Anna       return Status(pybuffer.takeError());
1369*21b8a8aeSLawrence D'Anna     memcpy(buf, pybuffer.get().get().buf, pybuffer.get().get().len);
1370*21b8a8aeSLawrence D'Anna     num_bytes = pybuffer.get().get().len;
1371*21b8a8aeSLawrence D'Anna     return Status();
1372*21b8a8aeSLawrence D'Anna   }
1373*21b8a8aeSLawrence D'Anna };
1374*21b8a8aeSLawrence D'Anna } // namespace
1375*21b8a8aeSLawrence D'Anna 
1376*21b8a8aeSLawrence D'Anna namespace {
1377*21b8a8aeSLawrence D'Anna class TextPythonFile : public PythonIOFile {
1378*21b8a8aeSLawrence D'Anna protected:
1379*21b8a8aeSLawrence D'Anna   int m_descriptor;
1380*21b8a8aeSLawrence D'Anna 
1381*21b8a8aeSLawrence D'Anna public:
1382*21b8a8aeSLawrence D'Anna   TextPythonFile(int fd, const PythonFile &file, bool borrowed)
1383*21b8a8aeSLawrence D'Anna       : PythonIOFile(file, borrowed),
1384*21b8a8aeSLawrence D'Anna         m_descriptor(File::DescriptorIsValid(fd) ? fd
1385*21b8a8aeSLawrence D'Anna                                                  : File::kInvalidDescriptor) {}
1386*21b8a8aeSLawrence D'Anna 
1387*21b8a8aeSLawrence D'Anna   int GetDescriptor() const override { return m_descriptor; }
1388*21b8a8aeSLawrence D'Anna 
1389*21b8a8aeSLawrence D'Anna   Status Write(const void *buf, size_t &num_bytes) override {
1390*21b8a8aeSLawrence D'Anna     GIL takeGIL;
1391*21b8a8aeSLawrence D'Anna     auto pystring =
1392*21b8a8aeSLawrence D'Anna         PythonString::FromUTF8(llvm::StringRef((const char *)buf, num_bytes));
1393*21b8a8aeSLawrence D'Anna     if (!pystring)
1394*21b8a8aeSLawrence D'Anna       return Status(pystring.takeError());
1395*21b8a8aeSLawrence D'Anna     num_bytes = 0;
1396*21b8a8aeSLawrence D'Anna     auto bytes_written =
1397*21b8a8aeSLawrence D'Anna         As<long long>(m_py_obj.CallMethod("write", pystring.get()));
1398*21b8a8aeSLawrence D'Anna     if (!bytes_written)
1399*21b8a8aeSLawrence D'Anna       return Status(bytes_written.takeError());
1400*21b8a8aeSLawrence D'Anna     if (bytes_written.get() < 0)
1401*21b8a8aeSLawrence D'Anna       return Status(".write() method returned a negative number!");
1402*21b8a8aeSLawrence D'Anna     static_assert(sizeof(long long) >= sizeof(size_t), "overflow");
1403*21b8a8aeSLawrence D'Anna     num_bytes = bytes_written.get();
1404*21b8a8aeSLawrence D'Anna     return Status();
1405*21b8a8aeSLawrence D'Anna   }
1406*21b8a8aeSLawrence D'Anna 
1407*21b8a8aeSLawrence D'Anna   Status Read(void *buf, size_t &num_bytes) override {
1408*21b8a8aeSLawrence D'Anna     GIL takeGIL;
1409*21b8a8aeSLawrence D'Anna     size_t num_chars = num_bytes / 6;
1410*21b8a8aeSLawrence D'Anna     size_t orig_num_bytes = num_bytes;
1411*21b8a8aeSLawrence D'Anna     num_bytes = 0;
1412*21b8a8aeSLawrence D'Anna     if (orig_num_bytes < 6) {
1413*21b8a8aeSLawrence D'Anna       return Status("can't read less than 6 bytes from a utf8 text stream");
1414*21b8a8aeSLawrence D'Anna     }
1415*21b8a8aeSLawrence D'Anna     auto pystring = As<PythonString>(
1416*21b8a8aeSLawrence D'Anna         m_py_obj.CallMethod("read", (unsigned long long)num_chars));
1417*21b8a8aeSLawrence D'Anna     if (!pystring)
1418*21b8a8aeSLawrence D'Anna       return Status(pystring.takeError());
1419*21b8a8aeSLawrence D'Anna     if (pystring.get().IsNone()) {
1420*21b8a8aeSLawrence D'Anna       // EOF
1421*21b8a8aeSLawrence D'Anna       return Status();
1422*21b8a8aeSLawrence D'Anna     }
1423*21b8a8aeSLawrence D'Anna     auto stringref = pystring.get().AsUTF8();
1424*21b8a8aeSLawrence D'Anna     if (!stringref)
1425*21b8a8aeSLawrence D'Anna       return Status(stringref.takeError());
1426*21b8a8aeSLawrence D'Anna     num_bytes = stringref.get().size();
1427*21b8a8aeSLawrence D'Anna     memcpy(buf, stringref.get().begin(), num_bytes);
1428*21b8a8aeSLawrence D'Anna     return Status();
1429*21b8a8aeSLawrence D'Anna   }
1430*21b8a8aeSLawrence D'Anna };
1431*21b8a8aeSLawrence D'Anna } // namespace
1432*21b8a8aeSLawrence D'Anna 
1433*21b8a8aeSLawrence D'Anna #endif
1434*21b8a8aeSLawrence D'Anna 
1435*21b8a8aeSLawrence D'Anna llvm::Expected<FileSP> PythonFile::ConvertToFile(bool borrowed) {
1436*21b8a8aeSLawrence D'Anna   if (!IsValid())
1437*21b8a8aeSLawrence D'Anna     return llvm::createStringError(llvm::inconvertibleErrorCode(),
1438*21b8a8aeSLawrence D'Anna                                    "invalid PythonFile");
1439*21b8a8aeSLawrence D'Anna 
1440*21b8a8aeSLawrence D'Anna   int fd = PyObject_AsFileDescriptor(m_py_obj);
1441*21b8a8aeSLawrence D'Anna   if (fd < 0) {
1442*21b8a8aeSLawrence D'Anna     PyErr_Clear();
1443*21b8a8aeSLawrence D'Anna     return ConvertToFileForcingUseOfScriptingIOMethods(borrowed);
1444*21b8a8aeSLawrence D'Anna   }
1445*21b8a8aeSLawrence D'Anna   auto options = GetOptionsForPyObject(*this);
1446*21b8a8aeSLawrence D'Anna   if (!options)
1447*21b8a8aeSLawrence D'Anna     return options.takeError();
1448*21b8a8aeSLawrence D'Anna 
1449*21b8a8aeSLawrence D'Anna   // LLDB and python will not share I/O buffers.  We should probably
1450*21b8a8aeSLawrence D'Anna   // flush the python buffers now.
1451*21b8a8aeSLawrence D'Anna   auto r = CallMethod("flush");
1452*21b8a8aeSLawrence D'Anna   if (!r)
1453*21b8a8aeSLawrence D'Anna     return r.takeError();
1454*21b8a8aeSLawrence D'Anna 
1455*21b8a8aeSLawrence D'Anna   FileSP file_sp;
1456*21b8a8aeSLawrence D'Anna   if (borrowed) {
1457*21b8a8aeSLawrence D'Anna     // In this case we we don't need to retain the python
1458*21b8a8aeSLawrence D'Anna     // object at all.
1459*21b8a8aeSLawrence D'Anna     file_sp = std::make_shared<NativeFile>(fd, options.get(), false);
1460*21b8a8aeSLawrence D'Anna   } else {
1461*21b8a8aeSLawrence D'Anna     file_sp = std::static_pointer_cast<File>(
1462*21b8a8aeSLawrence D'Anna         std::make_shared<SimplePythonFile>(*this, borrowed, fd, options.get()));
1463*21b8a8aeSLawrence D'Anna   }
1464*21b8a8aeSLawrence D'Anna   if (!file_sp->IsValid())
1465*21b8a8aeSLawrence D'Anna     return llvm::createStringError(llvm::inconvertibleErrorCode(),
1466*21b8a8aeSLawrence D'Anna                                    "invalid File");
1467*21b8a8aeSLawrence D'Anna 
1468*21b8a8aeSLawrence D'Anna   return file_sp;
1469*21b8a8aeSLawrence D'Anna }
1470*21b8a8aeSLawrence D'Anna 
1471*21b8a8aeSLawrence D'Anna llvm::Expected<FileSP>
1472*21b8a8aeSLawrence D'Anna PythonFile::ConvertToFileForcingUseOfScriptingIOMethods(bool borrowed) {
1473*21b8a8aeSLawrence D'Anna 
1474*21b8a8aeSLawrence D'Anna   assert(!PyErr_Occurred());
1475*21b8a8aeSLawrence D'Anna 
1476*21b8a8aeSLawrence D'Anna   if (!IsValid())
1477*21b8a8aeSLawrence D'Anna     return llvm::createStringError(llvm::inconvertibleErrorCode(),
1478*21b8a8aeSLawrence D'Anna                                    "invalid PythonFile");
1479*21b8a8aeSLawrence D'Anna 
1480*21b8a8aeSLawrence D'Anna #if PY_MAJOR_VERSION < 3
1481*21b8a8aeSLawrence D'Anna 
1482*21b8a8aeSLawrence D'Anna   return llvm::createStringError(llvm::inconvertibleErrorCode(),
1483*21b8a8aeSLawrence D'Anna                                  "not supported on python 2");
1484*21b8a8aeSLawrence D'Anna 
1485*21b8a8aeSLawrence D'Anna #else
1486*21b8a8aeSLawrence D'Anna 
1487*21b8a8aeSLawrence D'Anna   int fd = PyObject_AsFileDescriptor(m_py_obj);
1488*21b8a8aeSLawrence D'Anna   if (fd < 0) {
1489*21b8a8aeSLawrence D'Anna     PyErr_Clear();
1490*21b8a8aeSLawrence D'Anna     fd = File::kInvalidDescriptor;
1491*21b8a8aeSLawrence D'Anna   }
1492*21b8a8aeSLawrence D'Anna 
1493*21b8a8aeSLawrence D'Anna   auto io_module = PythonModule::Import("io");
1494*21b8a8aeSLawrence D'Anna   if (!io_module)
1495*21b8a8aeSLawrence D'Anna     return io_module.takeError();
1496*21b8a8aeSLawrence D'Anna   auto textIOBase = io_module.get().Get("TextIOBase");
1497*21b8a8aeSLawrence D'Anna   if (!textIOBase)
1498*21b8a8aeSLawrence D'Anna     return textIOBase.takeError();
1499*21b8a8aeSLawrence D'Anna   auto rawIOBase = io_module.get().Get("RawIOBase");
1500*21b8a8aeSLawrence D'Anna   if (!rawIOBase)
1501*21b8a8aeSLawrence D'Anna     return rawIOBase.takeError();
1502*21b8a8aeSLawrence D'Anna   auto bufferedIOBase = io_module.get().Get("BufferedIOBase");
1503*21b8a8aeSLawrence D'Anna   if (!bufferedIOBase)
1504*21b8a8aeSLawrence D'Anna     return bufferedIOBase.takeError();
1505*21b8a8aeSLawrence D'Anna 
1506*21b8a8aeSLawrence D'Anna   FileSP file_sp;
1507*21b8a8aeSLawrence D'Anna 
1508*21b8a8aeSLawrence D'Anna   auto isTextIO = IsInstance(textIOBase.get());
1509*21b8a8aeSLawrence D'Anna   if (!isTextIO)
1510*21b8a8aeSLawrence D'Anna     return isTextIO.takeError();
1511*21b8a8aeSLawrence D'Anna   if (isTextIO.get())
1512*21b8a8aeSLawrence D'Anna     file_sp = std::static_pointer_cast<File>(
1513*21b8a8aeSLawrence D'Anna         std::make_shared<TextPythonFile>(fd, *this, borrowed));
1514*21b8a8aeSLawrence D'Anna 
1515*21b8a8aeSLawrence D'Anna   auto isRawIO = IsInstance(rawIOBase.get());
1516*21b8a8aeSLawrence D'Anna   if (!isRawIO)
1517*21b8a8aeSLawrence D'Anna     return isRawIO.takeError();
1518*21b8a8aeSLawrence D'Anna   auto isBufferedIO = IsInstance(bufferedIOBase.get());
1519*21b8a8aeSLawrence D'Anna   if (!isBufferedIO)
1520*21b8a8aeSLawrence D'Anna     return isBufferedIO.takeError();
1521*21b8a8aeSLawrence D'Anna 
1522*21b8a8aeSLawrence D'Anna   if (isRawIO.get() || isBufferedIO.get()) {
1523*21b8a8aeSLawrence D'Anna     file_sp = std::static_pointer_cast<File>(
1524*21b8a8aeSLawrence D'Anna         std::make_shared<BinaryPythonFile>(fd, *this, borrowed));
1525*21b8a8aeSLawrence D'Anna   }
1526*21b8a8aeSLawrence D'Anna 
1527*21b8a8aeSLawrence D'Anna   if (!file_sp)
1528*21b8a8aeSLawrence D'Anna     return llvm::createStringError(llvm::inconvertibleErrorCode(),
1529*21b8a8aeSLawrence D'Anna                                    "python file is neither text nor binary");
1530*21b8a8aeSLawrence D'Anna 
1531*21b8a8aeSLawrence D'Anna   if (!file_sp->IsValid())
1532*21b8a8aeSLawrence D'Anna     return llvm::createStringError(llvm::inconvertibleErrorCode(),
1533*21b8a8aeSLawrence D'Anna                                    "invalid File");
1534*21b8a8aeSLawrence D'Anna 
1535*21b8a8aeSLawrence D'Anna   return file_sp;
1536*21b8a8aeSLawrence D'Anna 
1537*21b8a8aeSLawrence D'Anna #endif
1538*21b8a8aeSLawrence D'Anna }
1539*21b8a8aeSLawrence D'Anna 
1540d68983e3SPavel Labath #endif
1541