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"
25*d9b553ecSLawrence D'Anna #include "llvm/Support/Casting.h"
26190fadcdSZachary Turner #include "llvm/Support/ConvertUTF.h"
272819136fSMichal Gorny #include "llvm/Support/Errno.h"
28190fadcdSZachary Turner 
292c1f46dcSZachary Turner #include <stdio.h>
302c1f46dcSZachary Turner 
312c1f46dcSZachary Turner using namespace lldb_private;
322c1f46dcSZachary Turner using namespace lldb;
33085328eeSLawrence D'Anna using namespace lldb_private::python;
34085328eeSLawrence D'Anna using llvm::Error;
35085328eeSLawrence D'Anna using llvm::Expected;
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();
47085328eeSLawrence D'Anna   return obj.get().AsLongLong();
48085328eeSLawrence D'Anna }
492c1f46dcSZachary Turner 
502783d817SJonas Devlieghere void StructuredPythonObject::Serialize(llvm::json::OStream &s) const {
512783d817SJonas Devlieghere   s.value(llvm::formatv("Python Obj: {0:X}", GetValue()).str());
522c1f46dcSZachary Turner }
532c1f46dcSZachary Turner 
542c1f46dcSZachary Turner // PythonObject
552c1f46dcSZachary Turner 
56b9c1b51eSKate Stone void PythonObject::Dump(Stream &strm) const {
57b9c1b51eSKate Stone   if (m_py_obj) {
582819136fSMichal Gorny     FILE *file = llvm::sys::RetryAfterSignal(nullptr, ::tmpfile);
59b9c1b51eSKate Stone     if (file) {
602c1f46dcSZachary Turner       ::PyObject_Print(m_py_obj, file, 0);
612c1f46dcSZachary Turner       const long length = ftell(file);
62b9c1b51eSKate Stone       if (length) {
632c1f46dcSZachary Turner         ::rewind(file);
642c1f46dcSZachary Turner         std::vector<char> file_contents(length, '\0');
65b9c1b51eSKate Stone         const size_t length_read =
66b9c1b51eSKate Stone             ::fread(file_contents.data(), 1, file_contents.size(), file);
672c1f46dcSZachary Turner         if (length_read > 0)
682c1f46dcSZachary Turner           strm.Write(file_contents.data(), length_read);
692c1f46dcSZachary Turner       }
702c1f46dcSZachary Turner       ::fclose(file);
712c1f46dcSZachary Turner     }
72b9c1b51eSKate Stone   } else
732c1f46dcSZachary Turner     strm.PutCString("NULL");
742c1f46dcSZachary Turner }
752c1f46dcSZachary Turner 
76b9c1b51eSKate Stone PyObjectType PythonObject::GetObjectType() const {
77f8b22f8fSZachary Turner   if (!IsAllocated())
782c1f46dcSZachary Turner     return PyObjectType::None;
792c1f46dcSZachary Turner 
807841efbbSZachary Turner   if (PythonModule::Check(m_py_obj))
817841efbbSZachary Turner     return PyObjectType::Module;
8218426935SZachary Turner   if (PythonList::Check(m_py_obj))
832c1f46dcSZachary Turner     return PyObjectType::List;
84a1405147SZachary Turner   if (PythonTuple::Check(m_py_obj))
85a1405147SZachary Turner     return PyObjectType::Tuple;
8618426935SZachary Turner   if (PythonDictionary::Check(m_py_obj))
872c1f46dcSZachary Turner     return PyObjectType::Dictionary;
8818426935SZachary Turner   if (PythonString::Check(m_py_obj))
8922c8efcdSZachary Turner     return PyObjectType::String;
905a72c02bSZachary Turner #if PY_MAJOR_VERSION >= 3
915a72c02bSZachary Turner   if (PythonBytes::Check(m_py_obj))
925a72c02bSZachary Turner     return PyObjectType::Bytes;
935a72c02bSZachary Turner #endif
94f9d6d204SZachary Turner   if (PythonByteArray::Check(m_py_obj))
95f9d6d204SZachary Turner     return PyObjectType::ByteArray;
96b81d715cSTatyana Krasnukha   if (PythonBoolean::Check(m_py_obj))
97b81d715cSTatyana Krasnukha     return PyObjectType::Boolean;
9818426935SZachary Turner   if (PythonInteger::Check(m_py_obj))
9922c8efcdSZachary Turner     return PyObjectType::Integer;
1009c40264fSZachary Turner   if (PythonFile::Check(m_py_obj))
1019c40264fSZachary Turner     return PyObjectType::File;
102a1405147SZachary Turner   if (PythonCallable::Check(m_py_obj))
103a1405147SZachary Turner     return PyObjectType::Callable;
1042c1f46dcSZachary Turner   return PyObjectType::Unknown;
1052c1f46dcSZachary Turner }
1062c1f46dcSZachary Turner 
107b9c1b51eSKate Stone PythonString PythonObject::Repr() const {
1082c1f46dcSZachary Turner   if (!m_py_obj)
1092c1f46dcSZachary Turner     return PythonString();
1102c1f46dcSZachary Turner   PyObject *repr = PyObject_Repr(m_py_obj);
1112c1f46dcSZachary Turner   if (!repr)
1122c1f46dcSZachary Turner     return PythonString();
113f8b22f8fSZachary Turner   return PythonString(PyRefType::Owned, repr);
1142c1f46dcSZachary Turner }
1152c1f46dcSZachary Turner 
116b9c1b51eSKate Stone PythonString PythonObject::Str() const {
1172c1f46dcSZachary Turner   if (!m_py_obj)
1182c1f46dcSZachary Turner     return PythonString();
1192c1f46dcSZachary Turner   PyObject *str = PyObject_Str(m_py_obj);
1202c1f46dcSZachary Turner   if (!str)
1212c1f46dcSZachary Turner     return PythonString();
122f8b22f8fSZachary Turner   return PythonString(PyRefType::Owned, str);
1232c1f46dcSZachary Turner }
1242c1f46dcSZachary Turner 
1257841efbbSZachary Turner PythonObject
126b9c1b51eSKate Stone PythonObject::ResolveNameWithDictionary(llvm::StringRef name,
127b9c1b51eSKate Stone                                         const PythonDictionary &dict) {
128c712bac7SJonas Devlieghere   size_t dot_pos = name.find('.');
129a1405147SZachary Turner   llvm::StringRef piece = name.substr(0, dot_pos);
130a1405147SZachary Turner   PythonObject result = dict.GetItemForKey(PythonString(piece));
131b9c1b51eSKate Stone   if (dot_pos == llvm::StringRef::npos) {
132a1405147SZachary Turner     // There was no dot, we're done.
133a1405147SZachary Turner     return result;
134a1405147SZachary Turner   }
135a1405147SZachary Turner 
136a1405147SZachary Turner   // There was a dot.  The remaining portion of the name should be looked up in
137a1405147SZachary Turner   // the context of the object that was found in the dictionary.
138a1405147SZachary Turner   return result.ResolveName(name.substr(dot_pos + 1));
1397841efbbSZachary Turner }
1407841efbbSZachary Turner 
141b9c1b51eSKate Stone PythonObject PythonObject::ResolveName(llvm::StringRef name) const {
14205097246SAdrian Prantl   // Resolve the name in the context of the specified object.  If, for example,
14305097246SAdrian Prantl   // `this` refers to a PyModule, then this will look for `name` in this
14405097246SAdrian Prantl   // module.  If `this` refers to a PyType, then it will resolve `name` as an
14505097246SAdrian Prantl   // attribute of that type.  If `this` refers to an instance of an object,
14605097246SAdrian Prantl   // then it will resolve `name` as the value of the specified field.
1477841efbbSZachary Turner   //
1487841efbbSZachary Turner   // This function handles dotted names so that, for example, if `m_py_obj`
14905097246SAdrian Prantl   // refers to the `sys` module, and `name` == "path.append", then it will find
15005097246SAdrian Prantl   // the function `sys.path.append`.
1517841efbbSZachary Turner 
152c712bac7SJonas Devlieghere   size_t dot_pos = name.find('.');
153b9c1b51eSKate Stone   if (dot_pos == llvm::StringRef::npos) {
15405097246SAdrian Prantl     // No dots in the name, we should be able to find the value immediately as
15505097246SAdrian Prantl     // an attribute of `m_py_obj`.
1567841efbbSZachary Turner     return GetAttributeValue(name);
1577841efbbSZachary Turner   }
1587841efbbSZachary Turner 
159b9c1b51eSKate Stone   // Look up the first piece of the name, and resolve the rest as a child of
160b9c1b51eSKate Stone   // that.
1617841efbbSZachary Turner   PythonObject parent = ResolveName(name.substr(0, dot_pos));
1627841efbbSZachary Turner   if (!parent.IsAllocated())
1637841efbbSZachary Turner     return PythonObject();
1647841efbbSZachary Turner 
1657841efbbSZachary Turner   // Tail recursion.. should be optimized by the compiler
1667841efbbSZachary Turner   return parent.ResolveName(name.substr(dot_pos + 1));
1677841efbbSZachary Turner }
1687841efbbSZachary Turner 
169b9c1b51eSKate Stone bool PythonObject::HasAttribute(llvm::StringRef attr) const {
1709c40264fSZachary Turner   if (!IsValid())
1719c40264fSZachary Turner     return false;
1729c40264fSZachary Turner   PythonString py_attr(attr);
1739c40264fSZachary Turner   return !!PyObject_HasAttr(m_py_obj, py_attr.get());
1749c40264fSZachary Turner }
1759c40264fSZachary Turner 
176b9c1b51eSKate Stone PythonObject PythonObject::GetAttributeValue(llvm::StringRef attr) const {
1777d6d218eSZachary Turner   if (!IsValid())
1787d6d218eSZachary Turner     return PythonObject();
1797d6d218eSZachary Turner 
1807d6d218eSZachary Turner   PythonString py_attr(attr);
1817d6d218eSZachary Turner   if (!PyObject_HasAttr(m_py_obj, py_attr.get()))
1827d6d218eSZachary Turner     return PythonObject();
1837d6d218eSZachary Turner 
1847d6d218eSZachary Turner   return PythonObject(PyRefType::Owned,
1857d6d218eSZachary Turner                       PyObject_GetAttr(m_py_obj, py_attr.get()));
1867d6d218eSZachary Turner }
1877d6d218eSZachary Turner 
188b9c1b51eSKate Stone StructuredData::ObjectSP PythonObject::CreateStructuredObject() const {
189b9c1b51eSKate Stone   switch (GetObjectType()) {
1902c1f46dcSZachary Turner   case PyObjectType::Dictionary:
191b9c1b51eSKate Stone     return PythonDictionary(PyRefType::Borrowed, m_py_obj)
192b9c1b51eSKate Stone         .CreateStructuredDictionary();
193b81d715cSTatyana Krasnukha   case PyObjectType::Boolean:
194b81d715cSTatyana Krasnukha     return PythonBoolean(PyRefType::Borrowed, m_py_obj)
195b81d715cSTatyana Krasnukha         .CreateStructuredBoolean();
1962c1f46dcSZachary Turner   case PyObjectType::Integer:
197b9c1b51eSKate Stone     return PythonInteger(PyRefType::Borrowed, m_py_obj)
198b9c1b51eSKate Stone         .CreateStructuredInteger();
1992c1f46dcSZachary Turner   case PyObjectType::List:
200f8b22f8fSZachary Turner     return PythonList(PyRefType::Borrowed, m_py_obj).CreateStructuredArray();
2012c1f46dcSZachary Turner   case PyObjectType::String:
202f8b22f8fSZachary Turner     return PythonString(PyRefType::Borrowed, m_py_obj).CreateStructuredString();
2035a72c02bSZachary Turner   case PyObjectType::Bytes:
2045a72c02bSZachary Turner     return PythonBytes(PyRefType::Borrowed, m_py_obj).CreateStructuredString();
205f9d6d204SZachary Turner   case PyObjectType::ByteArray:
206b9c1b51eSKate Stone     return PythonByteArray(PyRefType::Borrowed, m_py_obj)
207b9c1b51eSKate Stone         .CreateStructuredString();
2082c1f46dcSZachary Turner   case PyObjectType::None:
2092c1f46dcSZachary Turner     return StructuredData::ObjectSP();
2102c1f46dcSZachary Turner   default:
2112c1f46dcSZachary Turner     return StructuredData::ObjectSP(new StructuredPythonObject(m_py_obj));
2122c1f46dcSZachary Turner   }
2132c1f46dcSZachary Turner }
2142c1f46dcSZachary Turner 
2152c1f46dcSZachary Turner // PythonString
216b9c1b51eSKate Stone PythonBytes::PythonBytes() : PythonObject() {}
2175a72c02bSZachary Turner 
218b9c1b51eSKate Stone PythonBytes::PythonBytes(llvm::ArrayRef<uint8_t> bytes) : PythonObject() {
2195a72c02bSZachary Turner   SetBytes(bytes);
2205a72c02bSZachary Turner }
2215a72c02bSZachary Turner 
222b9c1b51eSKate Stone PythonBytes::PythonBytes(const uint8_t *bytes, size_t length) : PythonObject() {
2235a72c02bSZachary Turner   SetBytes(llvm::ArrayRef<uint8_t>(bytes, length));
2245a72c02bSZachary Turner }
2255a72c02bSZachary Turner 
226b9c1b51eSKate Stone PythonBytes::PythonBytes(PyRefType type, PyObject *py_obj) : PythonObject() {
2275a72c02bSZachary Turner   Reset(type, py_obj); // Use "Reset()" to ensure that py_obj is a string
2285a72c02bSZachary Turner }
2295a72c02bSZachary Turner 
230b9c1b51eSKate Stone PythonBytes::~PythonBytes() {}
2315a72c02bSZachary Turner 
232b9c1b51eSKate Stone bool PythonBytes::Check(PyObject *py_obj) {
2335a72c02bSZachary Turner   if (!py_obj)
2345a72c02bSZachary Turner     return false;
235a6682a41SJonas Devlieghere   return PyBytes_Check(py_obj);
2365a72c02bSZachary Turner }
2375a72c02bSZachary Turner 
238b9c1b51eSKate Stone void PythonBytes::Reset(PyRefType type, PyObject *py_obj) {
23905097246SAdrian Prantl   // Grab the desired reference type so that if we end up rejecting `py_obj` it
24005097246SAdrian Prantl   // still gets decremented if necessary.
2415a72c02bSZachary Turner   PythonObject result(type, py_obj);
2425a72c02bSZachary Turner 
243b9c1b51eSKate Stone   if (!PythonBytes::Check(py_obj)) {
2445a72c02bSZachary Turner     PythonObject::Reset();
2455a72c02bSZachary Turner     return;
2465a72c02bSZachary Turner   }
2475a72c02bSZachary Turner 
248b9c1b51eSKate Stone   // Calling PythonObject::Reset(const PythonObject&) will lead to stack
24905097246SAdrian Prantl   // overflow since it calls back into the virtual implementation.
2505a72c02bSZachary Turner   PythonObject::Reset(PyRefType::Borrowed, result.get());
2515a72c02bSZachary Turner }
2525a72c02bSZachary Turner 
253b9c1b51eSKate Stone llvm::ArrayRef<uint8_t> PythonBytes::GetBytes() const {
2545a72c02bSZachary Turner   if (!IsValid())
2555a72c02bSZachary Turner     return llvm::ArrayRef<uint8_t>();
2565a72c02bSZachary Turner 
2575a72c02bSZachary Turner   Py_ssize_t size;
2585a72c02bSZachary Turner   char *c;
2595a72c02bSZachary Turner 
2605a72c02bSZachary Turner   PyBytes_AsStringAndSize(m_py_obj, &c, &size);
2615a72c02bSZachary Turner   return llvm::ArrayRef<uint8_t>(reinterpret_cast<uint8_t *>(c), size);
2625a72c02bSZachary Turner }
2635a72c02bSZachary Turner 
264b9c1b51eSKate Stone size_t PythonBytes::GetSize() const {
2655a72c02bSZachary Turner   if (!IsValid())
2665a72c02bSZachary Turner     return 0;
2675a72c02bSZachary Turner   return PyBytes_Size(m_py_obj);
2685a72c02bSZachary Turner }
2695a72c02bSZachary Turner 
270b9c1b51eSKate Stone void PythonBytes::SetBytes(llvm::ArrayRef<uint8_t> bytes) {
2715a72c02bSZachary Turner   const char *data = reinterpret_cast<const char *>(bytes.data());
2725a72c02bSZachary Turner   PyObject *py_bytes = PyBytes_FromStringAndSize(data, bytes.size());
2735a72c02bSZachary Turner   PythonObject::Reset(PyRefType::Owned, py_bytes);
2745a72c02bSZachary Turner }
2755a72c02bSZachary Turner 
276b9c1b51eSKate Stone StructuredData::StringSP PythonBytes::CreateStructuredString() const {
2775a72c02bSZachary Turner   StructuredData::StringSP result(new StructuredData::String);
2785a72c02bSZachary Turner   Py_ssize_t size;
2795a72c02bSZachary Turner   char *c;
2805a72c02bSZachary Turner   PyBytes_AsStringAndSize(m_py_obj, &c, &size);
2815a72c02bSZachary Turner   result->SetValue(std::string(c, size));
2825a72c02bSZachary Turner   return result;
2835a72c02bSZachary Turner }
2845a72c02bSZachary Turner 
285b9c1b51eSKate Stone PythonByteArray::PythonByteArray(llvm::ArrayRef<uint8_t> bytes)
286b9c1b51eSKate Stone     : PythonByteArray(bytes.data(), bytes.size()) {}
287f9d6d204SZachary Turner 
288b9c1b51eSKate Stone PythonByteArray::PythonByteArray(const uint8_t *bytes, size_t length) {
289f9d6d204SZachary Turner   const char *str = reinterpret_cast<const char *>(bytes);
290f9d6d204SZachary Turner   Reset(PyRefType::Owned, PyByteArray_FromStringAndSize(str, length));
291f9d6d204SZachary Turner }
292f9d6d204SZachary Turner 
293b9c1b51eSKate Stone PythonByteArray::PythonByteArray(PyRefType type, PyObject *o) {
294f9d6d204SZachary Turner   Reset(type, o);
295f9d6d204SZachary Turner }
296f9d6d204SZachary Turner 
297b9c1b51eSKate Stone PythonByteArray::PythonByteArray(const PythonBytes &object)
298b9c1b51eSKate Stone     : PythonObject(object) {}
299f9d6d204SZachary Turner 
300b9c1b51eSKate Stone PythonByteArray::~PythonByteArray() {}
301f9d6d204SZachary Turner 
302b9c1b51eSKate Stone bool PythonByteArray::Check(PyObject *py_obj) {
303f9d6d204SZachary Turner   if (!py_obj)
304f9d6d204SZachary Turner     return false;
305a6682a41SJonas Devlieghere   return PyByteArray_Check(py_obj);
306f9d6d204SZachary Turner }
307f9d6d204SZachary Turner 
308b9c1b51eSKate Stone void PythonByteArray::Reset(PyRefType type, PyObject *py_obj) {
30905097246SAdrian Prantl   // Grab the desired reference type so that if we end up rejecting `py_obj` it
31005097246SAdrian Prantl   // still gets decremented if necessary.
311f9d6d204SZachary Turner   PythonObject result(type, py_obj);
312f9d6d204SZachary Turner 
313b9c1b51eSKate Stone   if (!PythonByteArray::Check(py_obj)) {
314f9d6d204SZachary Turner     PythonObject::Reset();
315f9d6d204SZachary Turner     return;
316f9d6d204SZachary Turner   }
317f9d6d204SZachary Turner 
318b9c1b51eSKate Stone   // Calling PythonObject::Reset(const PythonObject&) will lead to stack
31905097246SAdrian Prantl   // overflow since it calls back into the virtual implementation.
320f9d6d204SZachary Turner   PythonObject::Reset(PyRefType::Borrowed, result.get());
321f9d6d204SZachary Turner }
322f9d6d204SZachary Turner 
323b9c1b51eSKate Stone llvm::ArrayRef<uint8_t> PythonByteArray::GetBytes() const {
324f9d6d204SZachary Turner   if (!IsValid())
325f9d6d204SZachary Turner     return llvm::ArrayRef<uint8_t>();
326f9d6d204SZachary Turner 
327f9d6d204SZachary Turner   char *c = PyByteArray_AsString(m_py_obj);
328f9d6d204SZachary Turner   size_t size = GetSize();
329f9d6d204SZachary Turner   return llvm::ArrayRef<uint8_t>(reinterpret_cast<uint8_t *>(c), size);
330f9d6d204SZachary Turner }
331f9d6d204SZachary Turner 
332b9c1b51eSKate Stone size_t PythonByteArray::GetSize() const {
333f9d6d204SZachary Turner   if (!IsValid())
334f9d6d204SZachary Turner     return 0;
335f9d6d204SZachary Turner 
336f9d6d204SZachary Turner   return PyByteArray_Size(m_py_obj);
337f9d6d204SZachary Turner }
338f9d6d204SZachary Turner 
339b9c1b51eSKate Stone StructuredData::StringSP PythonByteArray::CreateStructuredString() const {
340f9d6d204SZachary Turner   StructuredData::StringSP result(new StructuredData::String);
341f9d6d204SZachary Turner   llvm::ArrayRef<uint8_t> bytes = GetBytes();
342f9d6d204SZachary Turner   const char *str = reinterpret_cast<const char *>(bytes.data());
343f9d6d204SZachary Turner   result->SetValue(std::string(str, bytes.size()));
344f9d6d204SZachary Turner   return result;
345f9d6d204SZachary Turner }
346f9d6d204SZachary Turner 
3475a72c02bSZachary Turner // PythonString
3482c1f46dcSZachary Turner 
349085328eeSLawrence D'Anna Expected<PythonString> PythonString::FromUTF8(llvm::StringRef string) {
350085328eeSLawrence D'Anna #if PY_MAJOR_VERSION >= 3
351085328eeSLawrence D'Anna   PyObject *str = PyUnicode_FromStringAndSize(string.data(), string.size());
352085328eeSLawrence D'Anna #else
353085328eeSLawrence D'Anna   PyObject *str = PyString_FromStringAndSize(string.data(), string.size());
354085328eeSLawrence D'Anna #endif
355085328eeSLawrence D'Anna   if (!str)
356085328eeSLawrence D'Anna     return llvm::make_error<PythonException>();
357085328eeSLawrence D'Anna   return Take<PythonString>(str);
358085328eeSLawrence D'Anna }
359085328eeSLawrence D'Anna 
360b9c1b51eSKate Stone PythonString::PythonString(PyRefType type, PyObject *py_obj) : PythonObject() {
361f8b22f8fSZachary Turner   Reset(type, py_obj); // Use "Reset()" to ensure that py_obj is a string
3622c1f46dcSZachary Turner }
3632c1f46dcSZachary Turner 
364b9c1b51eSKate Stone PythonString::PythonString(llvm::StringRef string) : PythonObject() {
36522c8efcdSZachary Turner   SetString(string);
3662c1f46dcSZachary Turner }
3672c1f46dcSZachary Turner 
368b9c1b51eSKate Stone PythonString::PythonString() : PythonObject() {}
3692c1f46dcSZachary Turner 
370b9c1b51eSKate Stone PythonString::~PythonString() {}
3712c1f46dcSZachary Turner 
372b9c1b51eSKate Stone bool PythonString::Check(PyObject *py_obj) {
37322c8efcdSZachary Turner   if (!py_obj)
37422c8efcdSZachary Turner     return false;
37518426935SZachary Turner 
3767d6d218eSZachary Turner   if (PyUnicode_Check(py_obj))
3777d6d218eSZachary Turner     return true;
3787d6d218eSZachary Turner #if PY_MAJOR_VERSION < 3
3797d6d218eSZachary Turner   if (PyString_Check(py_obj))
3807d6d218eSZachary Turner     return true;
38122c8efcdSZachary Turner #endif
3827d6d218eSZachary Turner   return false;
38322c8efcdSZachary Turner }
38422c8efcdSZachary Turner 
385b9c1b51eSKate Stone void PythonString::Reset(PyRefType type, PyObject *py_obj) {
38605097246SAdrian Prantl   // Grab the desired reference type so that if we end up rejecting `py_obj` it
38705097246SAdrian Prantl   // still gets decremented if necessary.
388f8b22f8fSZachary Turner   PythonObject result(type, py_obj);
389f8b22f8fSZachary Turner 
390b9c1b51eSKate Stone   if (!PythonString::Check(py_obj)) {
391f8b22f8fSZachary Turner     PythonObject::Reset();
392f8b22f8fSZachary Turner     return;
39322c8efcdSZachary Turner   }
3947d6d218eSZachary Turner #if PY_MAJOR_VERSION < 3
3957d6d218eSZachary Turner   // In Python 2, Don't store PyUnicode objects directly, because we need
3967d6d218eSZachary Turner   // access to their underlying character buffers which Python 2 doesn't
3977d6d218eSZachary Turner   // provide.
398085328eeSLawrence D'Anna   if (PyUnicode_Check(py_obj)) {
399085328eeSLawrence D'Anna     PyObject *s = PyUnicode_AsUTF8String(result.get());
400085328eeSLawrence D'Anna     if (s == NULL)
401085328eeSLawrence D'Anna       PyErr_Clear();
402085328eeSLawrence D'Anna     result.Reset(PyRefType::Owned, s);
403085328eeSLawrence D'Anna   }
4047d6d218eSZachary Turner #endif
405b9c1b51eSKate Stone   // Calling PythonObject::Reset(const PythonObject&) will lead to stack
40605097246SAdrian Prantl   // overflow since it calls back into the virtual implementation.
407f8b22f8fSZachary Turner   PythonObject::Reset(PyRefType::Borrowed, result.get());
4082c1f46dcSZachary Turner }
4092c1f46dcSZachary Turner 
410b9c1b51eSKate Stone llvm::StringRef PythonString::GetString() const {
411085328eeSLawrence D'Anna   auto s = AsUTF8();
412085328eeSLawrence D'Anna   if (!s) {
413085328eeSLawrence D'Anna     llvm::consumeError(s.takeError());
414085328eeSLawrence D'Anna     return llvm::StringRef("");
415085328eeSLawrence D'Anna   }
416085328eeSLawrence D'Anna   return s.get();
417085328eeSLawrence D'Anna }
418085328eeSLawrence D'Anna 
419085328eeSLawrence D'Anna Expected<llvm::StringRef> PythonString::AsUTF8() const {
42018426935SZachary Turner   if (!IsValid())
421085328eeSLawrence D'Anna     return nullDeref();
42218426935SZachary Turner 
42322c8efcdSZachary Turner   Py_ssize_t size;
4245457b426SPavel Labath   const char *data;
42518426935SZachary Turner 
42618426935SZachary Turner #if PY_MAJOR_VERSION >= 3
4275457b426SPavel Labath   data = PyUnicode_AsUTF8AndSize(m_py_obj, &size);
42818426935SZachary Turner #else
429085328eeSLawrence D'Anna   char *c = NULL;
430085328eeSLawrence D'Anna   int r = PyString_AsStringAndSize(m_py_obj, &c, &size);
431085328eeSLawrence D'Anna   if (r < 0)
432085328eeSLawrence D'Anna     c = NULL;
4335457b426SPavel Labath   data = c;
43418426935SZachary Turner #endif
435085328eeSLawrence D'Anna 
436085328eeSLawrence D'Anna   if (!data)
437085328eeSLawrence D'Anna     return exception();
438085328eeSLawrence D'Anna 
4395457b426SPavel Labath   return llvm::StringRef(data, size);
44022c8efcdSZachary Turner }
4412c1f46dcSZachary Turner 
442b9c1b51eSKate Stone size_t PythonString::GetSize() const {
443b9c1b51eSKate Stone   if (IsValid()) {
44418426935SZachary Turner #if PY_MAJOR_VERSION >= 3
44518426935SZachary Turner     return PyUnicode_GetSize(m_py_obj);
44618426935SZachary Turner #else
44718426935SZachary Turner     return PyString_Size(m_py_obj);
44818426935SZachary Turner #endif
44918426935SZachary Turner   }
4502c1f46dcSZachary Turner   return 0;
4512c1f46dcSZachary Turner }
4522c1f46dcSZachary Turner 
453b9c1b51eSKate Stone void PythonString::SetString(llvm::StringRef string) {
454085328eeSLawrence D'Anna   auto s = FromUTF8(string);
455085328eeSLawrence D'Anna   if (!s) {
456085328eeSLawrence D'Anna     llvm::consumeError(s.takeError());
457085328eeSLawrence D'Anna     Reset();
458085328eeSLawrence D'Anna   } else {
459085328eeSLawrence D'Anna     PythonObject::Reset(std::move(s.get()));
460085328eeSLawrence D'Anna   }
4612c1f46dcSZachary Turner }
4622c1f46dcSZachary Turner 
463b9c1b51eSKate Stone StructuredData::StringSP PythonString::CreateStructuredString() const {
4642c1f46dcSZachary Turner   StructuredData::StringSP result(new StructuredData::String);
4652c1f46dcSZachary Turner   result->SetValue(GetString());
4662c1f46dcSZachary Turner   return result;
4672c1f46dcSZachary Turner }
4682c1f46dcSZachary Turner 
4692c1f46dcSZachary Turner // PythonInteger
4702c1f46dcSZachary Turner 
471b9c1b51eSKate Stone PythonInteger::PythonInteger() : PythonObject() {}
4727d6d218eSZachary Turner 
473f8b22f8fSZachary Turner PythonInteger::PythonInteger(PyRefType type, PyObject *py_obj)
474b9c1b51eSKate Stone     : PythonObject() {
475f8b22f8fSZachary Turner   Reset(type, py_obj); // Use "Reset()" to ensure that py_obj is a integer type
4762c1f46dcSZachary Turner }
4772c1f46dcSZachary Turner 
478b9c1b51eSKate Stone PythonInteger::PythonInteger(int64_t value) : PythonObject() {
4792c1f46dcSZachary Turner   SetInteger(value);
4802c1f46dcSZachary Turner }
4812c1f46dcSZachary Turner 
482b9c1b51eSKate Stone PythonInteger::~PythonInteger() {}
4832c1f46dcSZachary Turner 
484b9c1b51eSKate Stone bool PythonInteger::Check(PyObject *py_obj) {
48522c8efcdSZachary Turner   if (!py_obj)
48622c8efcdSZachary Turner     return false;
48722c8efcdSZachary Turner 
48822c8efcdSZachary Turner #if PY_MAJOR_VERSION >= 3
48905097246SAdrian Prantl   // Python 3 does not have PyInt_Check.  There is only one type of integral
49005097246SAdrian Prantl   // value, long.
49122c8efcdSZachary Turner   return PyLong_Check(py_obj);
49222c8efcdSZachary Turner #else
49322c8efcdSZachary Turner   return PyLong_Check(py_obj) || PyInt_Check(py_obj);
49422c8efcdSZachary Turner #endif
4952c1f46dcSZachary Turner }
4962c1f46dcSZachary Turner 
497b9c1b51eSKate Stone void PythonInteger::Reset(PyRefType type, PyObject *py_obj) {
49805097246SAdrian Prantl   // Grab the desired reference type so that if we end up rejecting `py_obj` it
49905097246SAdrian Prantl   // still gets decremented if necessary.
500f8b22f8fSZachary Turner   PythonObject result(type, py_obj);
501f8b22f8fSZachary Turner 
502b9c1b51eSKate Stone   if (!PythonInteger::Check(py_obj)) {
503f8b22f8fSZachary Turner     PythonObject::Reset();
504f8b22f8fSZachary Turner     return;
50522c8efcdSZachary Turner   }
50622c8efcdSZachary Turner 
50722c8efcdSZachary Turner #if PY_MAJOR_VERSION < 3
50805097246SAdrian Prantl   // Always store this as a PyLong, which makes interoperability between Python
50905097246SAdrian Prantl   // 2.x and Python 3.x easier.  This is only necessary in 2.x, since 3.x
51005097246SAdrian Prantl   // doesn't even have a PyInt.
511b9c1b51eSKate Stone   if (PyInt_Check(py_obj)) {
512f8b22f8fSZachary Turner     // Since we converted the original object to a different type, the new
51305097246SAdrian Prantl     // object is an owned object regardless of the ownership semantics
51405097246SAdrian Prantl     // requested by the user.
515f8b22f8fSZachary Turner     result.Reset(PyRefType::Owned, PyLong_FromLongLong(PyInt_AsLong(py_obj)));
51622c8efcdSZachary Turner   }
51722c8efcdSZachary Turner #endif
51822c8efcdSZachary Turner 
519b9c1b51eSKate Stone   assert(PyLong_Check(result.get()) &&
520b9c1b51eSKate Stone          "Couldn't get a PyLong from this PyObject");
52122c8efcdSZachary Turner 
522b9c1b51eSKate Stone   // Calling PythonObject::Reset(const PythonObject&) will lead to stack
52305097246SAdrian Prantl   // overflow since it calls back into the virtual implementation.
524f8b22f8fSZachary Turner   PythonObject::Reset(PyRefType::Borrowed, result.get());
5252c1f46dcSZachary Turner }
5262c1f46dcSZachary Turner 
527b9c1b51eSKate Stone int64_t PythonInteger::GetInteger() const {
528b9c1b51eSKate Stone   if (m_py_obj) {
529b9c1b51eSKate Stone     assert(PyLong_Check(m_py_obj) &&
530b9c1b51eSKate Stone            "PythonInteger::GetInteger has a PyObject that isn't a PyLong");
53122c8efcdSZachary Turner 
532008ec446SGreg Clayton     int overflow = 0;
533008ec446SGreg Clayton     int64_t result = PyLong_AsLongLongAndOverflow(m_py_obj, &overflow);
534b9c1b51eSKate Stone     if (overflow != 0) {
53505097246SAdrian Prantl       // We got an integer that overflows, like 18446744072853913392L we can't
53605097246SAdrian Prantl       // use PyLong_AsLongLong() as it will return 0xffffffffffffffff. If we
53705097246SAdrian Prantl       // use the unsigned long long it will work as expected.
538008ec446SGreg Clayton       const uint64_t uval = PyLong_AsUnsignedLongLong(m_py_obj);
5394f730dc7SIlia K       result = static_cast<int64_t>(uval);
540008ec446SGreg Clayton     }
541008ec446SGreg Clayton     return result;
5422c1f46dcSZachary Turner   }
5432c1f46dcSZachary Turner   return UINT64_MAX;
5442c1f46dcSZachary Turner }
5452c1f46dcSZachary Turner 
546b9c1b51eSKate Stone void PythonInteger::SetInteger(int64_t value) {
547f8b22f8fSZachary Turner   PythonObject::Reset(PyRefType::Owned, PyLong_FromLongLong(value));
5482c1f46dcSZachary Turner }
5492c1f46dcSZachary Turner 
550b9c1b51eSKate Stone StructuredData::IntegerSP PythonInteger::CreateStructuredInteger() const {
5512c1f46dcSZachary Turner   StructuredData::IntegerSP result(new StructuredData::Integer);
5522c1f46dcSZachary Turner   result->SetValue(GetInteger());
5532c1f46dcSZachary Turner   return result;
5542c1f46dcSZachary Turner }
5552c1f46dcSZachary Turner 
556b81d715cSTatyana Krasnukha // PythonBoolean
557b81d715cSTatyana Krasnukha 
558b81d715cSTatyana Krasnukha PythonBoolean::PythonBoolean(PyRefType type, PyObject *py_obj)
559b81d715cSTatyana Krasnukha     : PythonObject() {
560b81d715cSTatyana Krasnukha   Reset(type, py_obj); // Use "Reset()" to ensure that py_obj is a boolean type
561b81d715cSTatyana Krasnukha }
562b81d715cSTatyana Krasnukha 
563b81d715cSTatyana Krasnukha PythonBoolean::PythonBoolean(bool value) {
564b81d715cSTatyana Krasnukha   SetValue(value);
565b81d715cSTatyana Krasnukha }
566b81d715cSTatyana Krasnukha 
567b81d715cSTatyana Krasnukha bool PythonBoolean::Check(PyObject *py_obj) {
568b81d715cSTatyana Krasnukha   return py_obj ? PyBool_Check(py_obj) : false;
569b81d715cSTatyana Krasnukha }
570b81d715cSTatyana Krasnukha 
571b81d715cSTatyana Krasnukha void PythonBoolean::Reset(PyRefType type, PyObject *py_obj) {
572b81d715cSTatyana Krasnukha   // Grab the desired reference type so that if we end up rejecting `py_obj` it
573b81d715cSTatyana Krasnukha   // still gets decremented if necessary.
574b81d715cSTatyana Krasnukha   PythonObject result(type, py_obj);
575b81d715cSTatyana Krasnukha 
576b81d715cSTatyana Krasnukha   if (!PythonBoolean::Check(py_obj)) {
577b81d715cSTatyana Krasnukha     PythonObject::Reset();
578b81d715cSTatyana Krasnukha     return;
579b81d715cSTatyana Krasnukha   }
580b81d715cSTatyana Krasnukha 
581b81d715cSTatyana Krasnukha   // Calling PythonObject::Reset(const PythonObject&) will lead to stack
582b81d715cSTatyana Krasnukha   // overflow since it calls back into the virtual implementation.
583b81d715cSTatyana Krasnukha   PythonObject::Reset(PyRefType::Borrowed, result.get());
584b81d715cSTatyana Krasnukha }
585b81d715cSTatyana Krasnukha 
586b81d715cSTatyana Krasnukha bool PythonBoolean::GetValue() const {
587b81d715cSTatyana Krasnukha   return m_py_obj ? PyObject_IsTrue(m_py_obj) : false;
588b81d715cSTatyana Krasnukha }
589b81d715cSTatyana Krasnukha 
590b81d715cSTatyana Krasnukha void PythonBoolean::SetValue(bool value) {
591b81d715cSTatyana Krasnukha   PythonObject::Reset(PyRefType::Owned, PyBool_FromLong(value));
592b81d715cSTatyana Krasnukha }
593b81d715cSTatyana Krasnukha 
594b81d715cSTatyana Krasnukha StructuredData::BooleanSP PythonBoolean::CreateStructuredBoolean() const {
595b81d715cSTatyana Krasnukha   StructuredData::BooleanSP result(new StructuredData::Boolean);
596b81d715cSTatyana Krasnukha   result->SetValue(GetValue());
597b81d715cSTatyana Krasnukha   return result;
598b81d715cSTatyana Krasnukha }
599b81d715cSTatyana Krasnukha 
6002c1f46dcSZachary Turner // PythonList
6012c1f46dcSZachary Turner 
602b9c1b51eSKate Stone PythonList::PythonList(PyInitialValue value) : PythonObject() {
603f8b22f8fSZachary Turner   if (value == PyInitialValue::Empty)
604f8b22f8fSZachary Turner     Reset(PyRefType::Owned, PyList_New(0));
6052c1f46dcSZachary Turner }
6062c1f46dcSZachary Turner 
607b9c1b51eSKate Stone PythonList::PythonList(int list_size) : PythonObject() {
60887f47729SZachary Turner   Reset(PyRefType::Owned, PyList_New(list_size));
60987f47729SZachary Turner }
61087f47729SZachary Turner 
611b9c1b51eSKate Stone PythonList::PythonList(PyRefType type, PyObject *py_obj) : PythonObject() {
612f8b22f8fSZachary Turner   Reset(type, py_obj); // Use "Reset()" to ensure that py_obj is a list
6132c1f46dcSZachary Turner }
6142c1f46dcSZachary Turner 
615b9c1b51eSKate Stone PythonList::~PythonList() {}
6162c1f46dcSZachary Turner 
617b9c1b51eSKate Stone bool PythonList::Check(PyObject *py_obj) {
61822c8efcdSZachary Turner   if (!py_obj)
61922c8efcdSZachary Turner     return false;
62022c8efcdSZachary Turner   return PyList_Check(py_obj);
62122c8efcdSZachary Turner }
62222c8efcdSZachary Turner 
623b9c1b51eSKate Stone void PythonList::Reset(PyRefType type, PyObject *py_obj) {
62405097246SAdrian Prantl   // Grab the desired reference type so that if we end up rejecting `py_obj` it
62505097246SAdrian Prantl   // still gets decremented if necessary.
626f8b22f8fSZachary Turner   PythonObject result(type, py_obj);
627f8b22f8fSZachary Turner 
628b9c1b51eSKate Stone   if (!PythonList::Check(py_obj)) {
629f8b22f8fSZachary Turner     PythonObject::Reset();
630f8b22f8fSZachary Turner     return;
63122c8efcdSZachary Turner   }
63222c8efcdSZachary Turner 
633b9c1b51eSKate Stone   // Calling PythonObject::Reset(const PythonObject&) will lead to stack
63405097246SAdrian Prantl   // overflow since it calls back into the virtual implementation.
635f8b22f8fSZachary Turner   PythonObject::Reset(PyRefType::Borrowed, result.get());
6362c1f46dcSZachary Turner }
6372c1f46dcSZachary Turner 
638b9c1b51eSKate Stone uint32_t PythonList::GetSize() const {
639f8b22f8fSZachary Turner   if (IsValid())
6402c1f46dcSZachary Turner     return PyList_GET_SIZE(m_py_obj);
6412c1f46dcSZachary Turner   return 0;
6422c1f46dcSZachary Turner }
6432c1f46dcSZachary Turner 
644b9c1b51eSKate Stone PythonObject PythonList::GetItemAtIndex(uint32_t index) const {
645f8b22f8fSZachary Turner   if (IsValid())
646f8b22f8fSZachary Turner     return PythonObject(PyRefType::Borrowed, PyList_GetItem(m_py_obj, index));
6472c1f46dcSZachary Turner   return PythonObject();
6482c1f46dcSZachary Turner }
6492c1f46dcSZachary Turner 
650b9c1b51eSKate Stone void PythonList::SetItemAtIndex(uint32_t index, const PythonObject &object) {
651b9c1b51eSKate Stone   if (IsAllocated() && object.IsValid()) {
652f8b22f8fSZachary Turner     // PyList_SetItem is documented to "steal" a reference, so we need to
653f8b22f8fSZachary Turner     // convert it to an owned reference by incrementing it.
654f8b22f8fSZachary Turner     Py_INCREF(object.get());
6552c1f46dcSZachary Turner     PyList_SetItem(m_py_obj, index, object.get());
6562c1f46dcSZachary Turner   }
657f8b22f8fSZachary Turner }
6582c1f46dcSZachary Turner 
659b9c1b51eSKate Stone void PythonList::AppendItem(const PythonObject &object) {
660b9c1b51eSKate Stone   if (IsAllocated() && object.IsValid()) {
661f8b22f8fSZachary Turner     // `PyList_Append` does *not* steal a reference, so do not call `Py_INCREF`
662f8b22f8fSZachary Turner     // here like we do with `PyList_SetItem`.
6632c1f46dcSZachary Turner     PyList_Append(m_py_obj, object.get());
6642c1f46dcSZachary Turner   }
665f8b22f8fSZachary Turner }
6662c1f46dcSZachary Turner 
667b9c1b51eSKate Stone StructuredData::ArraySP PythonList::CreateStructuredArray() const {
6682c1f46dcSZachary Turner   StructuredData::ArraySP result(new StructuredData::Array);
6692c1f46dcSZachary Turner   uint32_t count = GetSize();
670b9c1b51eSKate Stone   for (uint32_t i = 0; i < count; ++i) {
6712c1f46dcSZachary Turner     PythonObject obj = GetItemAtIndex(i);
6722c1f46dcSZachary Turner     result->AddItem(obj.CreateStructuredObject());
6732c1f46dcSZachary Turner   }
6742c1f46dcSZachary Turner   return result;
6752c1f46dcSZachary Turner }
6762c1f46dcSZachary Turner 
677a1405147SZachary Turner // PythonTuple
678a1405147SZachary Turner 
679b9c1b51eSKate Stone PythonTuple::PythonTuple(PyInitialValue value) : PythonObject() {
680a1405147SZachary Turner   if (value == PyInitialValue::Empty)
681a1405147SZachary Turner     Reset(PyRefType::Owned, PyTuple_New(0));
682a1405147SZachary Turner }
683a1405147SZachary Turner 
684b9c1b51eSKate Stone PythonTuple::PythonTuple(int tuple_size) : PythonObject() {
685a1405147SZachary Turner   Reset(PyRefType::Owned, PyTuple_New(tuple_size));
686a1405147SZachary Turner }
687a1405147SZachary Turner 
688b9c1b51eSKate Stone PythonTuple::PythonTuple(PyRefType type, PyObject *py_obj) : PythonObject() {
689a1405147SZachary Turner   Reset(type, py_obj); // Use "Reset()" to ensure that py_obj is a tuple
690a1405147SZachary Turner }
691a1405147SZachary Turner 
692b9c1b51eSKate Stone PythonTuple::PythonTuple(std::initializer_list<PythonObject> objects) {
693a1405147SZachary Turner   m_py_obj = PyTuple_New(objects.size());
694a1405147SZachary Turner 
695a1405147SZachary Turner   uint32_t idx = 0;
696b9c1b51eSKate Stone   for (auto object : objects) {
697a1405147SZachary Turner     if (object.IsValid())
698a1405147SZachary Turner       SetItemAtIndex(idx, object);
699a1405147SZachary Turner     idx++;
700a1405147SZachary Turner   }
701a1405147SZachary Turner }
702a1405147SZachary Turner 
703b9c1b51eSKate Stone PythonTuple::PythonTuple(std::initializer_list<PyObject *> objects) {
704a1405147SZachary Turner   m_py_obj = PyTuple_New(objects.size());
705a1405147SZachary Turner 
706a1405147SZachary Turner   uint32_t idx = 0;
707b9c1b51eSKate Stone   for (auto py_object : objects) {
708a1405147SZachary Turner     PythonObject object(PyRefType::Borrowed, py_object);
709a1405147SZachary Turner     if (object.IsValid())
710a1405147SZachary Turner       SetItemAtIndex(idx, object);
711a1405147SZachary Turner     idx++;
712a1405147SZachary Turner   }
713a1405147SZachary Turner }
714a1405147SZachary Turner 
715b9c1b51eSKate Stone PythonTuple::~PythonTuple() {}
716a1405147SZachary Turner 
717b9c1b51eSKate Stone bool PythonTuple::Check(PyObject *py_obj) {
718a1405147SZachary Turner   if (!py_obj)
719a1405147SZachary Turner     return false;
720a1405147SZachary Turner   return PyTuple_Check(py_obj);
721a1405147SZachary Turner }
722a1405147SZachary Turner 
723b9c1b51eSKate Stone void PythonTuple::Reset(PyRefType type, PyObject *py_obj) {
72405097246SAdrian Prantl   // Grab the desired reference type so that if we end up rejecting `py_obj` it
72505097246SAdrian Prantl   // still gets decremented if necessary.
726a1405147SZachary Turner   PythonObject result(type, py_obj);
727a1405147SZachary Turner 
728b9c1b51eSKate Stone   if (!PythonTuple::Check(py_obj)) {
729a1405147SZachary Turner     PythonObject::Reset();
730a1405147SZachary Turner     return;
731a1405147SZachary Turner   }
732a1405147SZachary Turner 
733b9c1b51eSKate Stone   // Calling PythonObject::Reset(const PythonObject&) will lead to stack
73405097246SAdrian Prantl   // overflow since it calls back into the virtual implementation.
735a1405147SZachary Turner   PythonObject::Reset(PyRefType::Borrowed, result.get());
736a1405147SZachary Turner }
737a1405147SZachary Turner 
738b9c1b51eSKate Stone uint32_t PythonTuple::GetSize() const {
739a1405147SZachary Turner   if (IsValid())
740a1405147SZachary Turner     return PyTuple_GET_SIZE(m_py_obj);
741a1405147SZachary Turner   return 0;
742a1405147SZachary Turner }
743a1405147SZachary Turner 
744b9c1b51eSKate Stone PythonObject PythonTuple::GetItemAtIndex(uint32_t index) const {
745a1405147SZachary Turner   if (IsValid())
746a1405147SZachary Turner     return PythonObject(PyRefType::Borrowed, PyTuple_GetItem(m_py_obj, index));
747a1405147SZachary Turner   return PythonObject();
748a1405147SZachary Turner }
749a1405147SZachary Turner 
750b9c1b51eSKate Stone void PythonTuple::SetItemAtIndex(uint32_t index, const PythonObject &object) {
751b9c1b51eSKate Stone   if (IsAllocated() && object.IsValid()) {
752a1405147SZachary Turner     // PyTuple_SetItem is documented to "steal" a reference, so we need to
753a1405147SZachary Turner     // convert it to an owned reference by incrementing it.
754a1405147SZachary Turner     Py_INCREF(object.get());
755a1405147SZachary Turner     PyTuple_SetItem(m_py_obj, index, object.get());
756a1405147SZachary Turner   }
757a1405147SZachary Turner }
758a1405147SZachary Turner 
759b9c1b51eSKate Stone StructuredData::ArraySP PythonTuple::CreateStructuredArray() const {
760a1405147SZachary Turner   StructuredData::ArraySP result(new StructuredData::Array);
761a1405147SZachary Turner   uint32_t count = GetSize();
762b9c1b51eSKate Stone   for (uint32_t i = 0; i < count; ++i) {
763a1405147SZachary Turner     PythonObject obj = GetItemAtIndex(i);
764a1405147SZachary Turner     result->AddItem(obj.CreateStructuredObject());
765a1405147SZachary Turner   }
766a1405147SZachary Turner   return result;
767a1405147SZachary Turner }
768a1405147SZachary Turner 
7692c1f46dcSZachary Turner // PythonDictionary
7702c1f46dcSZachary Turner 
771b9c1b51eSKate Stone PythonDictionary::PythonDictionary(PyInitialValue value) : PythonObject() {
772f8b22f8fSZachary Turner   if (value == PyInitialValue::Empty)
773f8b22f8fSZachary Turner     Reset(PyRefType::Owned, PyDict_New());
7742c1f46dcSZachary Turner }
7752c1f46dcSZachary Turner 
776f8b22f8fSZachary Turner PythonDictionary::PythonDictionary(PyRefType type, PyObject *py_obj)
777b9c1b51eSKate Stone     : PythonObject() {
778f8b22f8fSZachary Turner   Reset(type, py_obj); // Use "Reset()" to ensure that py_obj is a dictionary
7792c1f46dcSZachary Turner }
7802c1f46dcSZachary Turner 
781b9c1b51eSKate Stone PythonDictionary::~PythonDictionary() {}
7822c1f46dcSZachary Turner 
783b9c1b51eSKate Stone bool PythonDictionary::Check(PyObject *py_obj) {
78422c8efcdSZachary Turner   if (!py_obj)
78522c8efcdSZachary Turner     return false;
78622c8efcdSZachary Turner 
78722c8efcdSZachary Turner   return PyDict_Check(py_obj);
78822c8efcdSZachary Turner }
78922c8efcdSZachary Turner 
790b9c1b51eSKate Stone void PythonDictionary::Reset(PyRefType type, PyObject *py_obj) {
79105097246SAdrian Prantl   // Grab the desired reference type so that if we end up rejecting `py_obj` it
79205097246SAdrian Prantl   // still gets decremented if necessary.
793f8b22f8fSZachary Turner   PythonObject result(type, py_obj);
794f8b22f8fSZachary Turner 
795b9c1b51eSKate Stone   if (!PythonDictionary::Check(py_obj)) {
796f8b22f8fSZachary Turner     PythonObject::Reset();
797f8b22f8fSZachary Turner     return;
79822c8efcdSZachary Turner   }
79922c8efcdSZachary Turner 
800b9c1b51eSKate Stone   // Calling PythonObject::Reset(const PythonObject&) will lead to stack
80105097246SAdrian Prantl   // overflow since it calls back into the virtual implementation.
802f8b22f8fSZachary Turner   PythonObject::Reset(PyRefType::Borrowed, result.get());
8032c1f46dcSZachary Turner }
8042c1f46dcSZachary Turner 
805b9c1b51eSKate Stone uint32_t PythonDictionary::GetSize() const {
806f8b22f8fSZachary Turner   if (IsValid())
8072c1f46dcSZachary Turner     return PyDict_Size(m_py_obj);
8082c1f46dcSZachary Turner   return 0;
8092c1f46dcSZachary Turner }
8102c1f46dcSZachary Turner 
811b9c1b51eSKate Stone PythonList PythonDictionary::GetKeys() const {
812f8b22f8fSZachary Turner   if (IsValid())
813f8b22f8fSZachary Turner     return PythonList(PyRefType::Owned, PyDict_Keys(m_py_obj));
814f8b22f8fSZachary Turner   return PythonList(PyInitialValue::Invalid);
8152c1f46dcSZachary Turner }
8162c1f46dcSZachary Turner 
817b9c1b51eSKate Stone PythonObject PythonDictionary::GetItemForKey(const PythonObject &key) const {
818f8b22f8fSZachary Turner   if (IsAllocated() && key.IsValid())
819b9c1b51eSKate Stone     return PythonObject(PyRefType::Borrowed,
820b9c1b51eSKate Stone                         PyDict_GetItem(m_py_obj, key.get()));
8212c1f46dcSZachary Turner   return PythonObject();
8222c1f46dcSZachary Turner }
8232c1f46dcSZachary Turner 
824b9c1b51eSKate Stone void PythonDictionary::SetItemForKey(const PythonObject &key,
825b9c1b51eSKate Stone                                      const PythonObject &value) {
826f8b22f8fSZachary Turner   if (IsAllocated() && key.IsValid() && value.IsValid())
8272c1f46dcSZachary Turner     PyDict_SetItem(m_py_obj, key.get(), value.get());
8282c1f46dcSZachary Turner }
8292c1f46dcSZachary Turner 
8302c1f46dcSZachary Turner StructuredData::DictionarySP
831b9c1b51eSKate Stone PythonDictionary::CreateStructuredDictionary() const {
8322c1f46dcSZachary Turner   StructuredData::DictionarySP result(new StructuredData::Dictionary);
8332c1f46dcSZachary Turner   PythonList keys(GetKeys());
8342c1f46dcSZachary Turner   uint32_t num_keys = keys.GetSize();
835b9c1b51eSKate Stone   for (uint32_t i = 0; i < num_keys; ++i) {
8362c1f46dcSZachary Turner     PythonObject key = keys.GetItemAtIndex(i);
8372c1f46dcSZachary Turner     PythonObject value = GetItemForKey(key);
8382c1f46dcSZachary Turner     StructuredData::ObjectSP structured_value = value.CreateStructuredObject();
839f8b22f8fSZachary Turner     result->AddItem(key.Str().GetString(), structured_value);
8402c1f46dcSZachary Turner   }
8412c1f46dcSZachary Turner   return result;
8422c1f46dcSZachary Turner }
8432c1f46dcSZachary Turner 
844b9c1b51eSKate Stone PythonModule::PythonModule() : PythonObject() {}
8457841efbbSZachary Turner 
846b9c1b51eSKate Stone PythonModule::PythonModule(PyRefType type, PyObject *py_obj) {
8477841efbbSZachary Turner   Reset(type, py_obj); // Use "Reset()" to ensure that py_obj is a module
8487841efbbSZachary Turner }
8497841efbbSZachary Turner 
850b9c1b51eSKate Stone PythonModule::~PythonModule() {}
8517841efbbSZachary Turner 
852b9c1b51eSKate Stone PythonModule PythonModule::BuiltinsModule() {
853a1405147SZachary Turner #if PY_MAJOR_VERSION >= 3
854a1405147SZachary Turner   return AddModule("builtins");
855a1405147SZachary Turner #else
856a1405147SZachary Turner   return AddModule("__builtin__");
857a1405147SZachary Turner #endif
858a1405147SZachary Turner }
859a1405147SZachary Turner 
860b9c1b51eSKate Stone PythonModule PythonModule::MainModule() { return AddModule("__main__"); }
861a1405147SZachary Turner 
862b9c1b51eSKate Stone PythonModule PythonModule::AddModule(llvm::StringRef module) {
863a1405147SZachary Turner   std::string str = module.str();
864a1405147SZachary Turner   return PythonModule(PyRefType::Borrowed, PyImport_AddModule(str.c_str()));
8657841efbbSZachary Turner }
8667841efbbSZachary Turner 
867085328eeSLawrence D'Anna Expected<PythonModule> PythonModule::Import(const char *name) {
868085328eeSLawrence D'Anna   PyObject *mod = PyImport_ImportModule(name);
869085328eeSLawrence D'Anna   if (!mod)
870085328eeSLawrence D'Anna     return exception();
871085328eeSLawrence D'Anna   return Take<PythonModule>(mod);
872085328eeSLawrence D'Anna }
873085328eeSLawrence D'Anna 
874085328eeSLawrence D'Anna Expected<PythonObject> PythonModule::Get(const char *name) {
875085328eeSLawrence D'Anna   if (!IsValid())
876085328eeSLawrence D'Anna     return nullDeref();
877085328eeSLawrence D'Anna   PyObject *dict = PyModule_GetDict(m_py_obj);
878085328eeSLawrence D'Anna   if (!dict)
879085328eeSLawrence D'Anna     return exception();
880085328eeSLawrence D'Anna   PyObject *item = PyDict_GetItemString(dict, name);
881085328eeSLawrence D'Anna   if (!item)
882085328eeSLawrence D'Anna     return exception();
883085328eeSLawrence D'Anna   return Retain<PythonObject>(item);
8842419f1d5SZachary Turner }
8852419f1d5SZachary Turner 
886b9c1b51eSKate Stone bool PythonModule::Check(PyObject *py_obj) {
8877841efbbSZachary Turner   if (!py_obj)
8887841efbbSZachary Turner     return false;
8897841efbbSZachary Turner 
8907841efbbSZachary Turner   return PyModule_Check(py_obj);
8917841efbbSZachary Turner }
8927841efbbSZachary Turner 
893b9c1b51eSKate Stone void PythonModule::Reset(PyRefType type, PyObject *py_obj) {
89405097246SAdrian Prantl   // Grab the desired reference type so that if we end up rejecting `py_obj` it
89505097246SAdrian Prantl   // still gets decremented if necessary.
8967841efbbSZachary Turner   PythonObject result(type, py_obj);
8977841efbbSZachary Turner 
898b9c1b51eSKate Stone   if (!PythonModule::Check(py_obj)) {
8997841efbbSZachary Turner     PythonObject::Reset();
9007841efbbSZachary Turner     return;
9017841efbbSZachary Turner   }
9027841efbbSZachary Turner 
903b9c1b51eSKate Stone   // Calling PythonObject::Reset(const PythonObject&) will lead to stack
90405097246SAdrian Prantl   // overflow since it calls back into the virtual implementation.
9057841efbbSZachary Turner   PythonObject::Reset(PyRefType::Borrowed, result.get());
9067841efbbSZachary Turner }
9077841efbbSZachary Turner 
908b9c1b51eSKate Stone PythonDictionary PythonModule::GetDictionary() const {
9097841efbbSZachary Turner   return PythonDictionary(PyRefType::Borrowed, PyModule_GetDict(m_py_obj));
9107841efbbSZachary Turner }
9117841efbbSZachary Turner 
912b9c1b51eSKate Stone PythonCallable::PythonCallable() : PythonObject() {}
913a1405147SZachary Turner 
914b9c1b51eSKate Stone PythonCallable::PythonCallable(PyRefType type, PyObject *py_obj) {
915a1405147SZachary Turner   Reset(type, py_obj); // Use "Reset()" to ensure that py_obj is a callable
916a1405147SZachary Turner }
917a1405147SZachary Turner 
918b9c1b51eSKate Stone PythonCallable::~PythonCallable() {}
919a1405147SZachary Turner 
920b9c1b51eSKate Stone bool PythonCallable::Check(PyObject *py_obj) {
921a1405147SZachary Turner   if (!py_obj)
922a1405147SZachary Turner     return false;
923a1405147SZachary Turner 
924a1405147SZachary Turner   return PyCallable_Check(py_obj);
925a1405147SZachary Turner }
926a1405147SZachary Turner 
927b9c1b51eSKate Stone void PythonCallable::Reset(PyRefType type, PyObject *py_obj) {
92805097246SAdrian Prantl   // Grab the desired reference type so that if we end up rejecting `py_obj` it
92905097246SAdrian Prantl   // still gets decremented if necessary.
930a1405147SZachary Turner   PythonObject result(type, py_obj);
931a1405147SZachary Turner 
932b9c1b51eSKate Stone   if (!PythonCallable::Check(py_obj)) {
933a1405147SZachary Turner     PythonObject::Reset();
934a1405147SZachary Turner     return;
935a1405147SZachary Turner   }
936a1405147SZachary Turner 
937b9c1b51eSKate Stone   // Calling PythonObject::Reset(const PythonObject&) will lead to stack
93805097246SAdrian Prantl   // overflow since it calls back into the virtual implementation.
939a1405147SZachary Turner   PythonObject::Reset(PyRefType::Borrowed, result.get());
940a1405147SZachary Turner }
941a1405147SZachary Turner 
94227a14f19SJim Ingham PythonCallable::ArgInfo PythonCallable::GetNumInitArguments() const {
94327a14f19SJim Ingham   ArgInfo result = {0, false, false, false};
94427a14f19SJim Ingham   if (!IsValid())
94527a14f19SJim Ingham     return result;
94627a14f19SJim Ingham 
94727a14f19SJim Ingham   PythonObject __init__ = GetAttributeValue("__init__");
94827a14f19SJim Ingham   if (__init__.IsValid() ) {
94927a14f19SJim Ingham     auto __init_callable__ = __init__.AsType<PythonCallable>();
95027a14f19SJim Ingham     if (__init_callable__.IsValid())
95127a14f19SJim Ingham       return __init_callable__.GetNumArguments();
95227a14f19SJim Ingham   }
95327a14f19SJim Ingham   return result;
95427a14f19SJim Ingham }
95527a14f19SJim Ingham 
956b9c1b51eSKate Stone PythonCallable::ArgInfo PythonCallable::GetNumArguments() const {
957a5d6765cSEnrico Granata   ArgInfo result = {0, false, false, false};
958a1405147SZachary Turner   if (!IsValid())
959b58fb2f4SZachary Turner     return result;
960a1405147SZachary Turner 
961a1405147SZachary Turner   PyObject *py_func_obj = m_py_obj;
962b9c1b51eSKate Stone   if (PyMethod_Check(py_func_obj)) {
963a1405147SZachary Turner     py_func_obj = PyMethod_GET_FUNCTION(py_func_obj);
964a5d6765cSEnrico Granata     PythonObject im_self = GetAttributeValue("im_self");
965a5d6765cSEnrico Granata     if (im_self.IsValid() && !im_self.IsNone())
966a5d6765cSEnrico Granata       result.is_bound_method = true;
967b9c1b51eSKate Stone   } else {
968a5d6765cSEnrico Granata     // see if this is a callable object with an __call__ method
969b9c1b51eSKate Stone     if (!PyFunction_Check(py_func_obj)) {
970a5d6765cSEnrico Granata       PythonObject __call__ = GetAttributeValue("__call__");
971b9c1b51eSKate Stone       if (__call__.IsValid()) {
972a5d6765cSEnrico Granata         auto __callable__ = __call__.AsType<PythonCallable>();
973b9c1b51eSKate Stone         if (__callable__.IsValid()) {
974a5d6765cSEnrico Granata           py_func_obj = PyMethod_GET_FUNCTION(__callable__.get());
975a5d6765cSEnrico Granata           PythonObject im_self = GetAttributeValue("im_self");
976a5d6765cSEnrico Granata           if (im_self.IsValid() && !im_self.IsNone())
977a5d6765cSEnrico Granata             result.is_bound_method = true;
978a5d6765cSEnrico Granata         }
979a5d6765cSEnrico Granata       }
980a5d6765cSEnrico Granata     }
981a5d6765cSEnrico Granata   }
982a1405147SZachary Turner 
983a1405147SZachary Turner   if (!py_func_obj)
984b58fb2f4SZachary Turner     return result;
985a1405147SZachary Turner 
986a1405147SZachary Turner   PyCodeObject *code = (PyCodeObject *)PyFunction_GET_CODE(py_func_obj);
987a1405147SZachary Turner   if (!code)
988b58fb2f4SZachary Turner     return result;
989a1405147SZachary Turner 
990b58fb2f4SZachary Turner   result.count = code->co_argcount;
991b58fb2f4SZachary Turner   result.has_varargs = !!(code->co_flags & CO_VARARGS);
992b58fb2f4SZachary Turner   result.has_kwargs = !!(code->co_flags & CO_VARKEYWORDS);
993b58fb2f4SZachary Turner   return result;
994b58fb2f4SZachary Turner }
995b58fb2f4SZachary Turner 
996b9c1b51eSKate Stone PythonObject PythonCallable::operator()() {
997b9c1b51eSKate Stone   return PythonObject(PyRefType::Owned, PyObject_CallObject(m_py_obj, nullptr));
998a1405147SZachary Turner }
999a1405147SZachary Turner 
1000b9c1b51eSKate Stone PythonObject PythonCallable::
1001b9c1b51eSKate Stone operator()(std::initializer_list<PyObject *> args) {
1002a1405147SZachary Turner   PythonTuple arg_tuple(args);
1003a1405147SZachary Turner   return PythonObject(PyRefType::Owned,
1004a1405147SZachary Turner                       PyObject_CallObject(m_py_obj, arg_tuple.get()));
1005a1405147SZachary Turner }
1006a1405147SZachary Turner 
1007b9c1b51eSKate Stone PythonObject PythonCallable::
1008b9c1b51eSKate Stone operator()(std::initializer_list<PythonObject> args) {
1009a1405147SZachary Turner   PythonTuple arg_tuple(args);
1010a1405147SZachary Turner   return PythonObject(PyRefType::Owned,
1011a1405147SZachary Turner                       PyObject_CallObject(m_py_obj, arg_tuple.get()));
1012a1405147SZachary Turner }
1013a1405147SZachary Turner 
1014b9c1b51eSKate Stone PythonFile::PythonFile() : PythonObject() {}
101532064024SZachary Turner 
1016b9c1b51eSKate Stone PythonFile::PythonFile(PyRefType type, PyObject *o) { Reset(type, o); }
10179c40264fSZachary Turner 
1018b9c1b51eSKate Stone PythonFile::~PythonFile() {}
10199c40264fSZachary Turner 
1020b9c1b51eSKate Stone bool PythonFile::Check(PyObject *py_obj) {
102196898eb6SLawrence D'Anna   if (!py_obj)
102296898eb6SLawrence D'Anna     return false;
10239c40264fSZachary Turner #if PY_MAJOR_VERSION < 3
102423502721SJason Molenda   return PyFile_Check(py_obj);
102523502721SJason Molenda #else
10269c40264fSZachary Turner   // In Python 3, there is no `PyFile_Check`, and in fact PyFile is not even a
10279c40264fSZachary Turner   // first-class object type anymore.  `PyFile_FromFd` is just a thin wrapper
102805097246SAdrian Prantl   // over `io.open()`, which returns some object derived from `io.IOBase`. As a
102905097246SAdrian Prantl   // result, the only way to detect a file in Python 3 is to check whether it
103021b8a8aeSLawrence D'Anna   // inherits from `io.IOBase`.
103121b8a8aeSLawrence D'Anna   auto io_module = PythonModule::Import("io");
103221b8a8aeSLawrence D'Anna   if (!io_module) {
103321b8a8aeSLawrence D'Anna     llvm::consumeError(io_module.takeError());
10349c40264fSZachary Turner     return false;
103521b8a8aeSLawrence D'Anna   }
103621b8a8aeSLawrence D'Anna   auto iobase = io_module.get().Get("IOBase");
103721b8a8aeSLawrence D'Anna   if (!iobase) {
103821b8a8aeSLawrence D'Anna     llvm::consumeError(iobase.takeError());
10399c40264fSZachary Turner     return false;
104021b8a8aeSLawrence D'Anna   }
104121b8a8aeSLawrence D'Anna   int r = PyObject_IsInstance(py_obj, iobase.get().get());
104221b8a8aeSLawrence D'Anna   if (r < 0) {
104321b8a8aeSLawrence D'Anna     llvm::consumeError(exception()); // clear the exception and log it.
104421b8a8aeSLawrence D'Anna     return false;
104521b8a8aeSLawrence D'Anna   }
104621b8a8aeSLawrence D'Anna   return !!r;
104723502721SJason Molenda #endif
10489c40264fSZachary Turner }
10499c40264fSZachary Turner 
1050b9c1b51eSKate Stone void PythonFile::Reset(PyRefType type, PyObject *py_obj) {
105105097246SAdrian Prantl   // Grab the desired reference type so that if we end up rejecting `py_obj` it
105205097246SAdrian Prantl   // still gets decremented if necessary.
10539c40264fSZachary Turner   PythonObject result(type, py_obj);
10549c40264fSZachary Turner 
105523502721SJason Molenda   if (!PythonFile::Check(py_obj)) {
10569c40264fSZachary Turner     PythonObject::Reset();
10579c40264fSZachary Turner     return;
10589c40264fSZachary Turner   }
10599c40264fSZachary Turner 
10609c40264fSZachary Turner   // Calling PythonObject::Reset(const PythonObject&) will lead to stack
10619c40264fSZachary Turner   // overflow since it calls back into the virtual implementation.
10629c40264fSZachary Turner   PythonObject::Reset(PyRefType::Borrowed, result.get());
10639c40264fSZachary Turner }
10649c40264fSZachary Turner 
10652fce1137SLawrence D'Anna FileUP PythonFile::GetUnderlyingFile() const {
1066eda01c31SZachary Turner   if (!IsValid())
10672fce1137SLawrence D'Anna     return nullptr;
1068eda01c31SZachary Turner 
1069eda01c31SZachary Turner   // We don't own the file descriptor returned by this function, make sure the
1070eda01c31SZachary Turner   // File object knows about that.
1071744959b9SEnrico Granata   PythonString py_mode = GetAttributeValue("mode").AsType<PythonString>();
107257504530SLawrence D'Anna   auto options = File::GetOptionsFromMode(py_mode.GetString());
107362c9fe42SLawrence D'Anna   if (!options) {
107462c9fe42SLawrence D'Anna     llvm::consumeError(options.takeError());
107562c9fe42SLawrence D'Anna     return nullptr;
107662c9fe42SLawrence D'Anna   }
107762c9fe42SLawrence D'Anna   auto file = std::unique_ptr<File>(new NativeFile(
107862c9fe42SLawrence D'Anna       PyObject_AsFileDescriptor(m_py_obj), options.get(), false));
10792fce1137SLawrence D'Anna   if (!file->IsValid())
10802fce1137SLawrence D'Anna     return nullptr;
10812fce1137SLawrence D'Anna   return file;
1082eda01c31SZachary Turner }
1083d68983e3SPavel Labath 
108421b8a8aeSLawrence D'Anna namespace {
108521b8a8aeSLawrence D'Anna class GIL {
108621b8a8aeSLawrence D'Anna public:
108721b8a8aeSLawrence D'Anna   GIL() {
108821b8a8aeSLawrence D'Anna     m_state = PyGILState_Ensure();
108921b8a8aeSLawrence D'Anna     assert(!PyErr_Occurred());
109021b8a8aeSLawrence D'Anna   }
109121b8a8aeSLawrence D'Anna   ~GIL() { PyGILState_Release(m_state); }
109221b8a8aeSLawrence D'Anna 
109321b8a8aeSLawrence D'Anna protected:
109421b8a8aeSLawrence D'Anna   PyGILState_STATE m_state;
109521b8a8aeSLawrence D'Anna };
109621b8a8aeSLawrence D'Anna } // namespace
109721b8a8aeSLawrence D'Anna 
1098085328eeSLawrence D'Anna const char *PythonException::toCString() const {
1099085328eeSLawrence D'Anna   if (!m_repr_bytes)
1100085328eeSLawrence D'Anna     return "unknown exception";
1101085328eeSLawrence D'Anna   return PyBytes_AS_STRING(m_repr_bytes);
1102085328eeSLawrence D'Anna }
1103085328eeSLawrence D'Anna 
1104085328eeSLawrence D'Anna PythonException::PythonException(const char *caller) {
1105085328eeSLawrence D'Anna   assert(PyErr_Occurred());
1106085328eeSLawrence D'Anna   m_exception_type = m_exception = m_traceback = m_repr_bytes = NULL;
1107085328eeSLawrence D'Anna   PyErr_Fetch(&m_exception_type, &m_exception, &m_traceback);
1108085328eeSLawrence D'Anna   PyErr_NormalizeException(&m_exception_type, &m_exception, &m_traceback);
1109085328eeSLawrence D'Anna   PyErr_Clear();
1110085328eeSLawrence D'Anna   if (m_exception) {
1111085328eeSLawrence D'Anna     PyObject *repr = PyObject_Repr(m_exception);
1112085328eeSLawrence D'Anna     if (repr) {
1113085328eeSLawrence D'Anna       m_repr_bytes = PyUnicode_AsEncodedString(repr, "utf-8", nullptr);
1114085328eeSLawrence D'Anna       if (!m_repr_bytes) {
1115085328eeSLawrence D'Anna         PyErr_Clear();
1116085328eeSLawrence D'Anna       }
1117085328eeSLawrence D'Anna       Py_XDECREF(repr);
1118085328eeSLawrence D'Anna     } else {
1119085328eeSLawrence D'Anna       PyErr_Clear();
1120085328eeSLawrence D'Anna     }
1121085328eeSLawrence D'Anna   }
1122085328eeSLawrence D'Anna   Log *log = GetLogIfAllCategoriesSet(LIBLLDB_LOG_SCRIPT);
1123085328eeSLawrence D'Anna   if (caller)
1124085328eeSLawrence D'Anna     LLDB_LOGF(log, "%s failed with exception: %s", caller, toCString());
1125085328eeSLawrence D'Anna   else
1126085328eeSLawrence D'Anna     LLDB_LOGF(log, "python exception: %s", toCString());
1127085328eeSLawrence D'Anna }
1128085328eeSLawrence D'Anna void PythonException::Restore() {
1129085328eeSLawrence D'Anna   if (m_exception_type && m_exception) {
1130085328eeSLawrence D'Anna     PyErr_Restore(m_exception_type, m_exception, m_traceback);
1131085328eeSLawrence D'Anna   } else {
1132085328eeSLawrence D'Anna     PyErr_SetString(PyExc_Exception, toCString());
1133085328eeSLawrence D'Anna   }
1134085328eeSLawrence D'Anna   m_exception_type = m_exception = m_traceback = NULL;
1135085328eeSLawrence D'Anna }
1136085328eeSLawrence D'Anna 
1137085328eeSLawrence D'Anna PythonException::~PythonException() {
1138085328eeSLawrence D'Anna   Py_XDECREF(m_exception_type);
1139085328eeSLawrence D'Anna   Py_XDECREF(m_exception);
1140085328eeSLawrence D'Anna   Py_XDECREF(m_traceback);
1141085328eeSLawrence D'Anna   Py_XDECREF(m_repr_bytes);
1142085328eeSLawrence D'Anna }
1143085328eeSLawrence D'Anna 
1144085328eeSLawrence D'Anna void PythonException::log(llvm::raw_ostream &OS) const { OS << toCString(); }
1145085328eeSLawrence D'Anna 
1146085328eeSLawrence D'Anna std::error_code PythonException::convertToErrorCode() const {
1147085328eeSLawrence D'Anna   return llvm::inconvertibleErrorCode();
1148085328eeSLawrence D'Anna }
1149085328eeSLawrence D'Anna 
1150085328eeSLawrence D'Anna char PythonException::ID = 0;
1151085328eeSLawrence D'Anna 
115262c9fe42SLawrence D'Anna llvm::Expected<File::OpenOptions>
115362c9fe42SLawrence D'Anna GetOptionsForPyObject(const PythonObject &obj) {
115421b8a8aeSLawrence D'Anna #if PY_MAJOR_VERSION >= 3
115562c9fe42SLawrence D'Anna   auto options = File::OpenOptions(0);
115621b8a8aeSLawrence D'Anna   auto readable = As<bool>(obj.CallMethod("readable"));
115721b8a8aeSLawrence D'Anna   if (!readable)
115821b8a8aeSLawrence D'Anna     return readable.takeError();
115921b8a8aeSLawrence D'Anna   auto writable = As<bool>(obj.CallMethod("writable"));
116021b8a8aeSLawrence D'Anna   if (!writable)
116121b8a8aeSLawrence D'Anna     return writable.takeError();
116221b8a8aeSLawrence D'Anna   if (readable.get())
116321b8a8aeSLawrence D'Anna     options |= File::eOpenOptionRead;
116421b8a8aeSLawrence D'Anna   if (writable.get())
116521b8a8aeSLawrence D'Anna     options |= File::eOpenOptionWrite;
116662c9fe42SLawrence D'Anna   return options;
116721b8a8aeSLawrence D'Anna #else
116821b8a8aeSLawrence D'Anna   PythonString py_mode = obj.GetAttributeValue("mode").AsType<PythonString>();
116962c9fe42SLawrence D'Anna   return File::GetOptionsFromMode(py_mode.GetString());
117021b8a8aeSLawrence D'Anna #endif
117121b8a8aeSLawrence D'Anna }
117221b8a8aeSLawrence D'Anna 
117321b8a8aeSLawrence D'Anna // Base class template for python files.   All it knows how to do
117421b8a8aeSLawrence D'Anna // is hold a reference to the python object and close or flush it
117521b8a8aeSLawrence D'Anna // when the File is closed.
117621b8a8aeSLawrence D'Anna namespace {
117721b8a8aeSLawrence D'Anna template <typename Base> class OwnedPythonFile : public Base {
117821b8a8aeSLawrence D'Anna public:
117921b8a8aeSLawrence D'Anna   template <typename... Args>
118021b8a8aeSLawrence D'Anna   OwnedPythonFile(const PythonFile &file, bool borrowed, Args... args)
118121b8a8aeSLawrence D'Anna       : Base(args...), m_py_obj(file), m_borrowed(borrowed) {
118221b8a8aeSLawrence D'Anna     assert(m_py_obj);
118321b8a8aeSLawrence D'Anna   }
118421b8a8aeSLawrence D'Anna 
118521b8a8aeSLawrence D'Anna   ~OwnedPythonFile() override {
118621b8a8aeSLawrence D'Anna     assert(m_py_obj);
118721b8a8aeSLawrence D'Anna     GIL takeGIL;
118821b8a8aeSLawrence D'Anna     Close();
118921b8a8aeSLawrence D'Anna     m_py_obj.Reset();
119021b8a8aeSLawrence D'Anna   }
119121b8a8aeSLawrence D'Anna 
119221b8a8aeSLawrence D'Anna   bool IsPythonSideValid() const {
119321b8a8aeSLawrence D'Anna     GIL takeGIL;
119421b8a8aeSLawrence D'Anna     auto closed = As<bool>(m_py_obj.GetAttribute("closed"));
119521b8a8aeSLawrence D'Anna     if (!closed) {
119621b8a8aeSLawrence D'Anna       llvm::consumeError(closed.takeError());
119721b8a8aeSLawrence D'Anna       return false;
119821b8a8aeSLawrence D'Anna     }
119921b8a8aeSLawrence D'Anna     return !closed.get();
120021b8a8aeSLawrence D'Anna   }
120121b8a8aeSLawrence D'Anna 
120221b8a8aeSLawrence D'Anna   bool IsValid() const override {
120321b8a8aeSLawrence D'Anna     return IsPythonSideValid() && Base::IsValid();
120421b8a8aeSLawrence D'Anna   }
120521b8a8aeSLawrence D'Anna 
120621b8a8aeSLawrence D'Anna   Status Close() override {
120721b8a8aeSLawrence D'Anna     assert(m_py_obj);
120821b8a8aeSLawrence D'Anna     Status py_error, base_error;
120921b8a8aeSLawrence D'Anna     GIL takeGIL;
121021b8a8aeSLawrence D'Anna     if (!m_borrowed) {
121121b8a8aeSLawrence D'Anna       auto r = m_py_obj.CallMethod("close");
121221b8a8aeSLawrence D'Anna       if (!r)
121321b8a8aeSLawrence D'Anna         py_error = Status(r.takeError());
121421b8a8aeSLawrence D'Anna     }
121521b8a8aeSLawrence D'Anna     base_error = Base::Close();
121621b8a8aeSLawrence D'Anna     if (py_error.Fail())
121721b8a8aeSLawrence D'Anna       return py_error;
121821b8a8aeSLawrence D'Anna     return base_error;
121921b8a8aeSLawrence D'Anna   };
122021b8a8aeSLawrence D'Anna 
1221*d9b553ecSLawrence D'Anna   PyObject *GetPythonObject() const {
1222*d9b553ecSLawrence D'Anna     assert(m_py_obj.IsValid());
1223*d9b553ecSLawrence D'Anna     return m_py_obj.get();
1224*d9b553ecSLawrence D'Anna   }
1225*d9b553ecSLawrence D'Anna 
1226*d9b553ecSLawrence D'Anna   static bool classof(const File *file) = delete;
1227*d9b553ecSLawrence D'Anna 
122821b8a8aeSLawrence D'Anna protected:
122921b8a8aeSLawrence D'Anna   PythonFile m_py_obj;
123021b8a8aeSLawrence D'Anna   bool m_borrowed;
123121b8a8aeSLawrence D'Anna };
123221b8a8aeSLawrence D'Anna } // namespace
123321b8a8aeSLawrence D'Anna 
123421b8a8aeSLawrence D'Anna // A SimplePythonFile is a OwnedPythonFile that just does all I/O as
123521b8a8aeSLawrence D'Anna // a NativeFile
123621b8a8aeSLawrence D'Anna namespace {
123721b8a8aeSLawrence D'Anna class SimplePythonFile : public OwnedPythonFile<NativeFile> {
123821b8a8aeSLawrence D'Anna public:
123921b8a8aeSLawrence D'Anna   SimplePythonFile(const PythonFile &file, bool borrowed, int fd,
124062c9fe42SLawrence D'Anna                    File::OpenOptions options)
124121b8a8aeSLawrence D'Anna       : OwnedPythonFile(file, borrowed, fd, options, false) {}
1242*d9b553ecSLawrence D'Anna 
1243*d9b553ecSLawrence D'Anna   static char ID;
1244*d9b553ecSLawrence D'Anna   bool isA(const void *classID) const override {
1245*d9b553ecSLawrence D'Anna     return classID == &ID || NativeFile::isA(classID);
1246*d9b553ecSLawrence D'Anna   }
1247*d9b553ecSLawrence D'Anna   static bool classof(const File *file) { return file->isA(&ID); }
124821b8a8aeSLawrence D'Anna };
1249*d9b553ecSLawrence D'Anna char SimplePythonFile::ID = 0;
125021b8a8aeSLawrence D'Anna } // namespace
125121b8a8aeSLawrence D'Anna 
125221b8a8aeSLawrence D'Anna #if PY_MAJOR_VERSION >= 3
125321b8a8aeSLawrence D'Anna 
125421b8a8aeSLawrence D'Anna namespace {
125521b8a8aeSLawrence D'Anna class PythonBuffer {
125621b8a8aeSLawrence D'Anna public:
125721b8a8aeSLawrence D'Anna   PythonBuffer &operator=(const PythonBuffer &) = delete;
125821b8a8aeSLawrence D'Anna   PythonBuffer(const PythonBuffer &) = delete;
125921b8a8aeSLawrence D'Anna 
126021b8a8aeSLawrence D'Anna   static Expected<PythonBuffer> Create(PythonObject &obj,
126121b8a8aeSLawrence D'Anna                                        int flags = PyBUF_SIMPLE) {
126221b8a8aeSLawrence D'Anna     Py_buffer py_buffer = {};
126321b8a8aeSLawrence D'Anna     PyObject_GetBuffer(obj.get(), &py_buffer, flags);
126421b8a8aeSLawrence D'Anna     if (!py_buffer.obj)
126521b8a8aeSLawrence D'Anna       return llvm::make_error<PythonException>();
126621b8a8aeSLawrence D'Anna     return PythonBuffer(py_buffer);
126721b8a8aeSLawrence D'Anna   }
126821b8a8aeSLawrence D'Anna 
126921b8a8aeSLawrence D'Anna   PythonBuffer(PythonBuffer &&other) {
127021b8a8aeSLawrence D'Anna     m_buffer = other.m_buffer;
127121b8a8aeSLawrence D'Anna     other.m_buffer.obj = nullptr;
127221b8a8aeSLawrence D'Anna   }
127321b8a8aeSLawrence D'Anna 
127421b8a8aeSLawrence D'Anna   ~PythonBuffer() {
127521b8a8aeSLawrence D'Anna     if (m_buffer.obj)
127621b8a8aeSLawrence D'Anna       PyBuffer_Release(&m_buffer);
127721b8a8aeSLawrence D'Anna   }
127821b8a8aeSLawrence D'Anna 
127921b8a8aeSLawrence D'Anna   Py_buffer &get() { return m_buffer; }
128021b8a8aeSLawrence D'Anna 
128121b8a8aeSLawrence D'Anna private:
128221b8a8aeSLawrence D'Anna   // takes ownership of the buffer.
128321b8a8aeSLawrence D'Anna   PythonBuffer(const Py_buffer &py_buffer) : m_buffer(py_buffer) {}
128421b8a8aeSLawrence D'Anna   Py_buffer m_buffer;
128521b8a8aeSLawrence D'Anna };
128621b8a8aeSLawrence D'Anna } // namespace
128721b8a8aeSLawrence D'Anna 
128821b8a8aeSLawrence D'Anna // Shared methods between TextPythonFile and BinaryPythonFile
128921b8a8aeSLawrence D'Anna namespace {
129021b8a8aeSLawrence D'Anna class PythonIOFile : public OwnedPythonFile<File> {
129121b8a8aeSLawrence D'Anna public:
129221b8a8aeSLawrence D'Anna   PythonIOFile(const PythonFile &file, bool borrowed)
129321b8a8aeSLawrence D'Anna       : OwnedPythonFile(file, borrowed) {}
129421b8a8aeSLawrence D'Anna 
129521b8a8aeSLawrence D'Anna   ~PythonIOFile() override { Close(); }
129621b8a8aeSLawrence D'Anna 
129721b8a8aeSLawrence D'Anna   bool IsValid() const override { return IsPythonSideValid(); }
129821b8a8aeSLawrence D'Anna 
129921b8a8aeSLawrence D'Anna   Status Close() override {
130021b8a8aeSLawrence D'Anna     assert(m_py_obj);
130121b8a8aeSLawrence D'Anna     GIL takeGIL;
130221b8a8aeSLawrence D'Anna     if (m_borrowed)
130321b8a8aeSLawrence D'Anna       return Flush();
130421b8a8aeSLawrence D'Anna     auto r = m_py_obj.CallMethod("close");
130521b8a8aeSLawrence D'Anna     if (!r)
130621b8a8aeSLawrence D'Anna       return Status(r.takeError());
130721b8a8aeSLawrence D'Anna     return Status();
130821b8a8aeSLawrence D'Anna   }
130921b8a8aeSLawrence D'Anna 
131021b8a8aeSLawrence D'Anna   Status Flush() override {
131121b8a8aeSLawrence D'Anna     GIL takeGIL;
131221b8a8aeSLawrence D'Anna     auto r = m_py_obj.CallMethod("flush");
131321b8a8aeSLawrence D'Anna     if (!r)
131421b8a8aeSLawrence D'Anna       return Status(r.takeError());
131521b8a8aeSLawrence D'Anna     return Status();
131621b8a8aeSLawrence D'Anna   }
131721b8a8aeSLawrence D'Anna 
1318*d9b553ecSLawrence D'Anna   Expected<File::OpenOptions> GetOptions() const override {
1319*d9b553ecSLawrence D'Anna     GIL takeGIL;
1320*d9b553ecSLawrence D'Anna     return GetOptionsForPyObject(m_py_obj);
1321*d9b553ecSLawrence D'Anna   }
1322*d9b553ecSLawrence D'Anna 
1323*d9b553ecSLawrence D'Anna   static char ID;
1324*d9b553ecSLawrence D'Anna   bool isA(const void *classID) const override {
1325*d9b553ecSLawrence D'Anna     return classID == &ID || File::isA(classID);
1326*d9b553ecSLawrence D'Anna   }
1327*d9b553ecSLawrence D'Anna   static bool classof(const File *file) { return file->isA(&ID); }
132821b8a8aeSLawrence D'Anna };
1329*d9b553ecSLawrence D'Anna char PythonIOFile::ID = 0;
133021b8a8aeSLawrence D'Anna } // namespace
133121b8a8aeSLawrence D'Anna 
133221b8a8aeSLawrence D'Anna namespace {
133321b8a8aeSLawrence D'Anna class BinaryPythonFile : public PythonIOFile {
133421b8a8aeSLawrence D'Anna protected:
133521b8a8aeSLawrence D'Anna   int m_descriptor;
133621b8a8aeSLawrence D'Anna 
133721b8a8aeSLawrence D'Anna public:
133821b8a8aeSLawrence D'Anna   BinaryPythonFile(int fd, const PythonFile &file, bool borrowed)
133921b8a8aeSLawrence D'Anna       : PythonIOFile(file, borrowed),
134021b8a8aeSLawrence D'Anna         m_descriptor(File::DescriptorIsValid(fd) ? fd
134121b8a8aeSLawrence D'Anna                                                  : File::kInvalidDescriptor) {}
134221b8a8aeSLawrence D'Anna 
134321b8a8aeSLawrence D'Anna   int GetDescriptor() const override { return m_descriptor; }
134421b8a8aeSLawrence D'Anna 
134521b8a8aeSLawrence D'Anna   Status Write(const void *buf, size_t &num_bytes) override {
134621b8a8aeSLawrence D'Anna     GIL takeGIL;
134721b8a8aeSLawrence D'Anna     PyObject *pybuffer_p = PyMemoryView_FromMemory(
134821b8a8aeSLawrence D'Anna         const_cast<char *>((const char *)buf), num_bytes, PyBUF_READ);
134921b8a8aeSLawrence D'Anna     if (!pybuffer_p)
135021b8a8aeSLawrence D'Anna       return Status(llvm::make_error<PythonException>());
135121b8a8aeSLawrence D'Anna     auto pybuffer = Take<PythonObject>(pybuffer_p);
135221b8a8aeSLawrence D'Anna     num_bytes = 0;
135321b8a8aeSLawrence D'Anna     auto bytes_written = As<long long>(m_py_obj.CallMethod("write", pybuffer));
135421b8a8aeSLawrence D'Anna     if (!bytes_written)
135521b8a8aeSLawrence D'Anna       return Status(bytes_written.takeError());
135621b8a8aeSLawrence D'Anna     if (bytes_written.get() < 0)
135721b8a8aeSLawrence D'Anna       return Status(".write() method returned a negative number!");
135821b8a8aeSLawrence D'Anna     static_assert(sizeof(long long) >= sizeof(size_t), "overflow");
135921b8a8aeSLawrence D'Anna     num_bytes = bytes_written.get();
136021b8a8aeSLawrence D'Anna     return Status();
136121b8a8aeSLawrence D'Anna   }
136221b8a8aeSLawrence D'Anna 
136321b8a8aeSLawrence D'Anna   Status Read(void *buf, size_t &num_bytes) override {
136421b8a8aeSLawrence D'Anna     GIL takeGIL;
136521b8a8aeSLawrence D'Anna     static_assert(sizeof(long long) >= sizeof(size_t), "overflow");
136621b8a8aeSLawrence D'Anna     auto pybuffer_obj =
136721b8a8aeSLawrence D'Anna         m_py_obj.CallMethod("read", (unsigned long long)num_bytes);
136821b8a8aeSLawrence D'Anna     if (!pybuffer_obj)
136921b8a8aeSLawrence D'Anna       return Status(pybuffer_obj.takeError());
137021b8a8aeSLawrence D'Anna     num_bytes = 0;
137121b8a8aeSLawrence D'Anna     if (pybuffer_obj.get().IsNone()) {
137221b8a8aeSLawrence D'Anna       // EOF
137321b8a8aeSLawrence D'Anna       num_bytes = 0;
137421b8a8aeSLawrence D'Anna       return Status();
137521b8a8aeSLawrence D'Anna     }
137621b8a8aeSLawrence D'Anna     auto pybuffer = PythonBuffer::Create(pybuffer_obj.get());
137721b8a8aeSLawrence D'Anna     if (!pybuffer)
137821b8a8aeSLawrence D'Anna       return Status(pybuffer.takeError());
137921b8a8aeSLawrence D'Anna     memcpy(buf, pybuffer.get().get().buf, pybuffer.get().get().len);
138021b8a8aeSLawrence D'Anna     num_bytes = pybuffer.get().get().len;
138121b8a8aeSLawrence D'Anna     return Status();
138221b8a8aeSLawrence D'Anna   }
138321b8a8aeSLawrence D'Anna };
138421b8a8aeSLawrence D'Anna } // namespace
138521b8a8aeSLawrence D'Anna 
138621b8a8aeSLawrence D'Anna namespace {
138721b8a8aeSLawrence D'Anna class TextPythonFile : public PythonIOFile {
138821b8a8aeSLawrence D'Anna protected:
138921b8a8aeSLawrence D'Anna   int m_descriptor;
139021b8a8aeSLawrence D'Anna 
139121b8a8aeSLawrence D'Anna public:
139221b8a8aeSLawrence D'Anna   TextPythonFile(int fd, const PythonFile &file, bool borrowed)
139321b8a8aeSLawrence D'Anna       : PythonIOFile(file, borrowed),
139421b8a8aeSLawrence D'Anna         m_descriptor(File::DescriptorIsValid(fd) ? fd
139521b8a8aeSLawrence D'Anna                                                  : File::kInvalidDescriptor) {}
139621b8a8aeSLawrence D'Anna 
139721b8a8aeSLawrence D'Anna   int GetDescriptor() const override { return m_descriptor; }
139821b8a8aeSLawrence D'Anna 
139921b8a8aeSLawrence D'Anna   Status Write(const void *buf, size_t &num_bytes) override {
140021b8a8aeSLawrence D'Anna     GIL takeGIL;
140121b8a8aeSLawrence D'Anna     auto pystring =
140221b8a8aeSLawrence D'Anna         PythonString::FromUTF8(llvm::StringRef((const char *)buf, num_bytes));
140321b8a8aeSLawrence D'Anna     if (!pystring)
140421b8a8aeSLawrence D'Anna       return Status(pystring.takeError());
140521b8a8aeSLawrence D'Anna     num_bytes = 0;
140621b8a8aeSLawrence D'Anna     auto bytes_written =
140721b8a8aeSLawrence D'Anna         As<long long>(m_py_obj.CallMethod("write", pystring.get()));
140821b8a8aeSLawrence D'Anna     if (!bytes_written)
140921b8a8aeSLawrence D'Anna       return Status(bytes_written.takeError());
141021b8a8aeSLawrence D'Anna     if (bytes_written.get() < 0)
141121b8a8aeSLawrence D'Anna       return Status(".write() method returned a negative number!");
141221b8a8aeSLawrence D'Anna     static_assert(sizeof(long long) >= sizeof(size_t), "overflow");
141321b8a8aeSLawrence D'Anna     num_bytes = bytes_written.get();
141421b8a8aeSLawrence D'Anna     return Status();
141521b8a8aeSLawrence D'Anna   }
141621b8a8aeSLawrence D'Anna 
141721b8a8aeSLawrence D'Anna   Status Read(void *buf, size_t &num_bytes) override {
141821b8a8aeSLawrence D'Anna     GIL takeGIL;
141921b8a8aeSLawrence D'Anna     size_t num_chars = num_bytes / 6;
142021b8a8aeSLawrence D'Anna     size_t orig_num_bytes = num_bytes;
142121b8a8aeSLawrence D'Anna     num_bytes = 0;
142221b8a8aeSLawrence D'Anna     if (orig_num_bytes < 6) {
142321b8a8aeSLawrence D'Anna       return Status("can't read less than 6 bytes from a utf8 text stream");
142421b8a8aeSLawrence D'Anna     }
142521b8a8aeSLawrence D'Anna     auto pystring = As<PythonString>(
142621b8a8aeSLawrence D'Anna         m_py_obj.CallMethod("read", (unsigned long long)num_chars));
142721b8a8aeSLawrence D'Anna     if (!pystring)
142821b8a8aeSLawrence D'Anna       return Status(pystring.takeError());
142921b8a8aeSLawrence D'Anna     if (pystring.get().IsNone()) {
143021b8a8aeSLawrence D'Anna       // EOF
143121b8a8aeSLawrence D'Anna       return Status();
143221b8a8aeSLawrence D'Anna     }
143321b8a8aeSLawrence D'Anna     auto stringref = pystring.get().AsUTF8();
143421b8a8aeSLawrence D'Anna     if (!stringref)
143521b8a8aeSLawrence D'Anna       return Status(stringref.takeError());
143621b8a8aeSLawrence D'Anna     num_bytes = stringref.get().size();
143721b8a8aeSLawrence D'Anna     memcpy(buf, stringref.get().begin(), num_bytes);
143821b8a8aeSLawrence D'Anna     return Status();
143921b8a8aeSLawrence D'Anna   }
144021b8a8aeSLawrence D'Anna };
144121b8a8aeSLawrence D'Anna } // namespace
144221b8a8aeSLawrence D'Anna 
144321b8a8aeSLawrence D'Anna #endif
144421b8a8aeSLawrence D'Anna 
144521b8a8aeSLawrence D'Anna llvm::Expected<FileSP> PythonFile::ConvertToFile(bool borrowed) {
144621b8a8aeSLawrence D'Anna   if (!IsValid())
144721b8a8aeSLawrence D'Anna     return llvm::createStringError(llvm::inconvertibleErrorCode(),
144821b8a8aeSLawrence D'Anna                                    "invalid PythonFile");
144921b8a8aeSLawrence D'Anna 
145021b8a8aeSLawrence D'Anna   int fd = PyObject_AsFileDescriptor(m_py_obj);
145121b8a8aeSLawrence D'Anna   if (fd < 0) {
145221b8a8aeSLawrence D'Anna     PyErr_Clear();
145321b8a8aeSLawrence D'Anna     return ConvertToFileForcingUseOfScriptingIOMethods(borrowed);
145421b8a8aeSLawrence D'Anna   }
145521b8a8aeSLawrence D'Anna   auto options = GetOptionsForPyObject(*this);
145621b8a8aeSLawrence D'Anna   if (!options)
145721b8a8aeSLawrence D'Anna     return options.takeError();
145821b8a8aeSLawrence D'Anna 
145921b8a8aeSLawrence D'Anna   // LLDB and python will not share I/O buffers.  We should probably
146021b8a8aeSLawrence D'Anna   // flush the python buffers now.
146121b8a8aeSLawrence D'Anna   auto r = CallMethod("flush");
146221b8a8aeSLawrence D'Anna   if (!r)
146321b8a8aeSLawrence D'Anna     return r.takeError();
146421b8a8aeSLawrence D'Anna 
146521b8a8aeSLawrence D'Anna   FileSP file_sp;
146621b8a8aeSLawrence D'Anna   if (borrowed) {
146721b8a8aeSLawrence D'Anna     // In this case we we don't need to retain the python
146821b8a8aeSLawrence D'Anna     // object at all.
146921b8a8aeSLawrence D'Anna     file_sp = std::make_shared<NativeFile>(fd, options.get(), false);
147021b8a8aeSLawrence D'Anna   } else {
147121b8a8aeSLawrence D'Anna     file_sp = std::static_pointer_cast<File>(
147221b8a8aeSLawrence D'Anna         std::make_shared<SimplePythonFile>(*this, borrowed, fd, options.get()));
147321b8a8aeSLawrence D'Anna   }
147421b8a8aeSLawrence D'Anna   if (!file_sp->IsValid())
147521b8a8aeSLawrence D'Anna     return llvm::createStringError(llvm::inconvertibleErrorCode(),
147621b8a8aeSLawrence D'Anna                                    "invalid File");
147721b8a8aeSLawrence D'Anna 
147821b8a8aeSLawrence D'Anna   return file_sp;
147921b8a8aeSLawrence D'Anna }
148021b8a8aeSLawrence D'Anna 
148121b8a8aeSLawrence D'Anna llvm::Expected<FileSP>
148221b8a8aeSLawrence D'Anna PythonFile::ConvertToFileForcingUseOfScriptingIOMethods(bool borrowed) {
148321b8a8aeSLawrence D'Anna 
148421b8a8aeSLawrence D'Anna   assert(!PyErr_Occurred());
148521b8a8aeSLawrence D'Anna 
148621b8a8aeSLawrence D'Anna   if (!IsValid())
148721b8a8aeSLawrence D'Anna     return llvm::createStringError(llvm::inconvertibleErrorCode(),
148821b8a8aeSLawrence D'Anna                                    "invalid PythonFile");
148921b8a8aeSLawrence D'Anna 
149021b8a8aeSLawrence D'Anna #if PY_MAJOR_VERSION < 3
149121b8a8aeSLawrence D'Anna 
149221b8a8aeSLawrence D'Anna   return llvm::createStringError(llvm::inconvertibleErrorCode(),
149321b8a8aeSLawrence D'Anna                                  "not supported on python 2");
149421b8a8aeSLawrence D'Anna 
149521b8a8aeSLawrence D'Anna #else
149621b8a8aeSLawrence D'Anna 
149721b8a8aeSLawrence D'Anna   int fd = PyObject_AsFileDescriptor(m_py_obj);
149821b8a8aeSLawrence D'Anna   if (fd < 0) {
149921b8a8aeSLawrence D'Anna     PyErr_Clear();
150021b8a8aeSLawrence D'Anna     fd = File::kInvalidDescriptor;
150121b8a8aeSLawrence D'Anna   }
150221b8a8aeSLawrence D'Anna 
150321b8a8aeSLawrence D'Anna   auto io_module = PythonModule::Import("io");
150421b8a8aeSLawrence D'Anna   if (!io_module)
150521b8a8aeSLawrence D'Anna     return io_module.takeError();
150621b8a8aeSLawrence D'Anna   auto textIOBase = io_module.get().Get("TextIOBase");
150721b8a8aeSLawrence D'Anna   if (!textIOBase)
150821b8a8aeSLawrence D'Anna     return textIOBase.takeError();
150921b8a8aeSLawrence D'Anna   auto rawIOBase = io_module.get().Get("RawIOBase");
151021b8a8aeSLawrence D'Anna   if (!rawIOBase)
151121b8a8aeSLawrence D'Anna     return rawIOBase.takeError();
151221b8a8aeSLawrence D'Anna   auto bufferedIOBase = io_module.get().Get("BufferedIOBase");
151321b8a8aeSLawrence D'Anna   if (!bufferedIOBase)
151421b8a8aeSLawrence D'Anna     return bufferedIOBase.takeError();
151521b8a8aeSLawrence D'Anna 
151621b8a8aeSLawrence D'Anna   FileSP file_sp;
151721b8a8aeSLawrence D'Anna 
151821b8a8aeSLawrence D'Anna   auto isTextIO = IsInstance(textIOBase.get());
151921b8a8aeSLawrence D'Anna   if (!isTextIO)
152021b8a8aeSLawrence D'Anna     return isTextIO.takeError();
152121b8a8aeSLawrence D'Anna   if (isTextIO.get())
152221b8a8aeSLawrence D'Anna     file_sp = std::static_pointer_cast<File>(
152321b8a8aeSLawrence D'Anna         std::make_shared<TextPythonFile>(fd, *this, borrowed));
152421b8a8aeSLawrence D'Anna 
152521b8a8aeSLawrence D'Anna   auto isRawIO = IsInstance(rawIOBase.get());
152621b8a8aeSLawrence D'Anna   if (!isRawIO)
152721b8a8aeSLawrence D'Anna     return isRawIO.takeError();
152821b8a8aeSLawrence D'Anna   auto isBufferedIO = IsInstance(bufferedIOBase.get());
152921b8a8aeSLawrence D'Anna   if (!isBufferedIO)
153021b8a8aeSLawrence D'Anna     return isBufferedIO.takeError();
153121b8a8aeSLawrence D'Anna 
153221b8a8aeSLawrence D'Anna   if (isRawIO.get() || isBufferedIO.get()) {
153321b8a8aeSLawrence D'Anna     file_sp = std::static_pointer_cast<File>(
153421b8a8aeSLawrence D'Anna         std::make_shared<BinaryPythonFile>(fd, *this, borrowed));
153521b8a8aeSLawrence D'Anna   }
153621b8a8aeSLawrence D'Anna 
153721b8a8aeSLawrence D'Anna   if (!file_sp)
153821b8a8aeSLawrence D'Anna     return llvm::createStringError(llvm::inconvertibleErrorCode(),
153921b8a8aeSLawrence D'Anna                                    "python file is neither text nor binary");
154021b8a8aeSLawrence D'Anna 
154121b8a8aeSLawrence D'Anna   if (!file_sp->IsValid())
154221b8a8aeSLawrence D'Anna     return llvm::createStringError(llvm::inconvertibleErrorCode(),
154321b8a8aeSLawrence D'Anna                                    "invalid File");
154421b8a8aeSLawrence D'Anna 
154521b8a8aeSLawrence D'Anna   return file_sp;
154621b8a8aeSLawrence D'Anna 
154721b8a8aeSLawrence D'Anna #endif
154821b8a8aeSLawrence D'Anna }
154921b8a8aeSLawrence D'Anna 
1550*d9b553ecSLawrence D'Anna Expected<PythonFile> PythonFile::FromFile(File &file, const char *mode) {
1551*d9b553ecSLawrence D'Anna   if (!file.IsValid())
1552*d9b553ecSLawrence D'Anna     return llvm::createStringError(llvm::inconvertibleErrorCode(),
1553*d9b553ecSLawrence D'Anna                                    "invalid file");
1554*d9b553ecSLawrence D'Anna 
1555*d9b553ecSLawrence D'Anna   if (auto *simple = llvm::dyn_cast<SimplePythonFile>(&file))
1556*d9b553ecSLawrence D'Anna     return Retain<PythonFile>(simple->GetPythonObject());
1557*d9b553ecSLawrence D'Anna #if PY_MAJOR_VERSION >= 3
1558*d9b553ecSLawrence D'Anna   if (auto *pythonio = llvm::dyn_cast<PythonIOFile>(&file))
1559*d9b553ecSLawrence D'Anna     return Retain<PythonFile>(pythonio->GetPythonObject());
1560*d9b553ecSLawrence D'Anna #endif
1561*d9b553ecSLawrence D'Anna 
1562*d9b553ecSLawrence D'Anna   if (!mode) {
1563*d9b553ecSLawrence D'Anna     auto m = file.GetOpenMode();
1564*d9b553ecSLawrence D'Anna     if (!m)
1565*d9b553ecSLawrence D'Anna       return m.takeError();
1566*d9b553ecSLawrence D'Anna     mode = m.get();
1567*d9b553ecSLawrence D'Anna   }
1568*d9b553ecSLawrence D'Anna 
1569*d9b553ecSLawrence D'Anna   PyObject *file_obj;
1570*d9b553ecSLawrence D'Anna #if PY_MAJOR_VERSION >= 3
1571*d9b553ecSLawrence D'Anna   file_obj = PyFile_FromFd(file.GetDescriptor(), nullptr, mode, -1, nullptr,
1572*d9b553ecSLawrence D'Anna                            "ignore", nullptr, 0);
1573*d9b553ecSLawrence D'Anna #else
1574*d9b553ecSLawrence D'Anna   // Read through the Python source, doesn't seem to modify these strings
1575*d9b553ecSLawrence D'Anna   char *cmode = const_cast<char *>(mode);
1576*d9b553ecSLawrence D'Anna   // We pass ::flush instead of ::fclose here so we borrow the FILE* --
1577*d9b553ecSLawrence D'Anna   // the lldb_private::File still owns it.
1578*d9b553ecSLawrence D'Anna   file_obj =
1579*d9b553ecSLawrence D'Anna       PyFile_FromFile(file.GetStream(), const_cast<char *>(""), cmode, ::fflush);
1580*d9b553ecSLawrence D'Anna #endif
1581*d9b553ecSLawrence D'Anna 
1582*d9b553ecSLawrence D'Anna   if (!file_obj)
1583*d9b553ecSLawrence D'Anna     return exception();
1584*d9b553ecSLawrence D'Anna 
1585*d9b553ecSLawrence D'Anna   return Take<PythonFile>(file_obj);
1586*d9b553ecSLawrence D'Anna }
1587*d9b553ecSLawrence D'Anna 
1588d68983e3SPavel Labath #endif
1589