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"
25d9b553ecSLawrence 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
2165a72c02bSZachary Turner 
217*d3bd5b3dSLawrence D'Anna PythonBytes::PythonBytes(llvm::ArrayRef<uint8_t> bytes) { SetBytes(bytes); }
2185a72c02bSZachary Turner 
219*d3bd5b3dSLawrence D'Anna PythonBytes::PythonBytes(const uint8_t *bytes, size_t length) {
2205a72c02bSZachary Turner   SetBytes(llvm::ArrayRef<uint8_t>(bytes, length));
2215a72c02bSZachary Turner }
2225a72c02bSZachary Turner 
223b9c1b51eSKate Stone bool PythonBytes::Check(PyObject *py_obj) {
2245a72c02bSZachary Turner   if (!py_obj)
2255a72c02bSZachary Turner     return false;
226a6682a41SJonas Devlieghere   return PyBytes_Check(py_obj);
2275a72c02bSZachary Turner }
2285a72c02bSZachary Turner 
229b9c1b51eSKate Stone llvm::ArrayRef<uint8_t> PythonBytes::GetBytes() const {
2305a72c02bSZachary Turner   if (!IsValid())
2315a72c02bSZachary Turner     return llvm::ArrayRef<uint8_t>();
2325a72c02bSZachary Turner 
2335a72c02bSZachary Turner   Py_ssize_t size;
2345a72c02bSZachary Turner   char *c;
2355a72c02bSZachary Turner 
2365a72c02bSZachary Turner   PyBytes_AsStringAndSize(m_py_obj, &c, &size);
2375a72c02bSZachary Turner   return llvm::ArrayRef<uint8_t>(reinterpret_cast<uint8_t *>(c), size);
2385a72c02bSZachary Turner }
2395a72c02bSZachary Turner 
240b9c1b51eSKate Stone size_t PythonBytes::GetSize() const {
2415a72c02bSZachary Turner   if (!IsValid())
2425a72c02bSZachary Turner     return 0;
2435a72c02bSZachary Turner   return PyBytes_Size(m_py_obj);
2445a72c02bSZachary Turner }
2455a72c02bSZachary Turner 
246b9c1b51eSKate Stone void PythonBytes::SetBytes(llvm::ArrayRef<uint8_t> bytes) {
2475a72c02bSZachary Turner   const char *data = reinterpret_cast<const char *>(bytes.data());
2485a72c02bSZachary Turner   PyObject *py_bytes = PyBytes_FromStringAndSize(data, bytes.size());
2495a72c02bSZachary Turner   PythonObject::Reset(PyRefType::Owned, py_bytes);
2505a72c02bSZachary Turner }
2515a72c02bSZachary Turner 
252b9c1b51eSKate Stone StructuredData::StringSP PythonBytes::CreateStructuredString() const {
2535a72c02bSZachary Turner   StructuredData::StringSP result(new StructuredData::String);
2545a72c02bSZachary Turner   Py_ssize_t size;
2555a72c02bSZachary Turner   char *c;
2565a72c02bSZachary Turner   PyBytes_AsStringAndSize(m_py_obj, &c, &size);
2575a72c02bSZachary Turner   result->SetValue(std::string(c, size));
2585a72c02bSZachary Turner   return result;
2595a72c02bSZachary Turner }
2605a72c02bSZachary Turner 
261b9c1b51eSKate Stone PythonByteArray::PythonByteArray(llvm::ArrayRef<uint8_t> bytes)
262b9c1b51eSKate Stone     : PythonByteArray(bytes.data(), bytes.size()) {}
263f9d6d204SZachary Turner 
264b9c1b51eSKate Stone PythonByteArray::PythonByteArray(const uint8_t *bytes, size_t length) {
265f9d6d204SZachary Turner   const char *str = reinterpret_cast<const char *>(bytes);
266f9d6d204SZachary Turner   Reset(PyRefType::Owned, PyByteArray_FromStringAndSize(str, length));
267f9d6d204SZachary Turner }
268f9d6d204SZachary Turner 
269b9c1b51eSKate Stone bool PythonByteArray::Check(PyObject *py_obj) {
270f9d6d204SZachary Turner   if (!py_obj)
271f9d6d204SZachary Turner     return false;
272a6682a41SJonas Devlieghere   return PyByteArray_Check(py_obj);
273f9d6d204SZachary Turner }
274f9d6d204SZachary Turner 
275b9c1b51eSKate Stone llvm::ArrayRef<uint8_t> PythonByteArray::GetBytes() const {
276f9d6d204SZachary Turner   if (!IsValid())
277f9d6d204SZachary Turner     return llvm::ArrayRef<uint8_t>();
278f9d6d204SZachary Turner 
279f9d6d204SZachary Turner   char *c = PyByteArray_AsString(m_py_obj);
280f9d6d204SZachary Turner   size_t size = GetSize();
281f9d6d204SZachary Turner   return llvm::ArrayRef<uint8_t>(reinterpret_cast<uint8_t *>(c), size);
282f9d6d204SZachary Turner }
283f9d6d204SZachary Turner 
284b9c1b51eSKate Stone size_t PythonByteArray::GetSize() const {
285f9d6d204SZachary Turner   if (!IsValid())
286f9d6d204SZachary Turner     return 0;
287f9d6d204SZachary Turner 
288f9d6d204SZachary Turner   return PyByteArray_Size(m_py_obj);
289f9d6d204SZachary Turner }
290f9d6d204SZachary Turner 
291b9c1b51eSKate Stone StructuredData::StringSP PythonByteArray::CreateStructuredString() const {
292f9d6d204SZachary Turner   StructuredData::StringSP result(new StructuredData::String);
293f9d6d204SZachary Turner   llvm::ArrayRef<uint8_t> bytes = GetBytes();
294f9d6d204SZachary Turner   const char *str = reinterpret_cast<const char *>(bytes.data());
295f9d6d204SZachary Turner   result->SetValue(std::string(str, bytes.size()));
296f9d6d204SZachary Turner   return result;
297f9d6d204SZachary Turner }
298f9d6d204SZachary Turner 
2995a72c02bSZachary Turner // PythonString
3002c1f46dcSZachary Turner 
301085328eeSLawrence D'Anna Expected<PythonString> PythonString::FromUTF8(llvm::StringRef string) {
302085328eeSLawrence D'Anna #if PY_MAJOR_VERSION >= 3
303085328eeSLawrence D'Anna   PyObject *str = PyUnicode_FromStringAndSize(string.data(), string.size());
304085328eeSLawrence D'Anna #else
305085328eeSLawrence D'Anna   PyObject *str = PyString_FromStringAndSize(string.data(), string.size());
306085328eeSLawrence D'Anna #endif
307085328eeSLawrence D'Anna   if (!str)
308085328eeSLawrence D'Anna     return llvm::make_error<PythonException>();
309085328eeSLawrence D'Anna   return Take<PythonString>(str);
310085328eeSLawrence D'Anna }
311085328eeSLawrence D'Anna 
312*d3bd5b3dSLawrence D'Anna PythonString::PythonString(llvm::StringRef string) { SetString(string); }
3132c1f46dcSZachary Turner 
314b9c1b51eSKate Stone bool PythonString::Check(PyObject *py_obj) {
31522c8efcdSZachary Turner   if (!py_obj)
31622c8efcdSZachary Turner     return false;
31718426935SZachary Turner 
3187d6d218eSZachary Turner   if (PyUnicode_Check(py_obj))
3197d6d218eSZachary Turner     return true;
3207d6d218eSZachary Turner #if PY_MAJOR_VERSION < 3
3217d6d218eSZachary Turner   if (PyString_Check(py_obj))
3227d6d218eSZachary Turner     return true;
32322c8efcdSZachary Turner #endif
3247d6d218eSZachary Turner   return false;
32522c8efcdSZachary Turner }
32622c8efcdSZachary Turner 
327*d3bd5b3dSLawrence D'Anna void PythonString::Convert(PyRefType &type, PyObject *&py_obj) {
3287d6d218eSZachary Turner #if PY_MAJOR_VERSION < 3
3297d6d218eSZachary Turner   // In Python 2, Don't store PyUnicode objects directly, because we need
3307d6d218eSZachary Turner   // access to their underlying character buffers which Python 2 doesn't
3317d6d218eSZachary Turner   // provide.
332085328eeSLawrence D'Anna   if (PyUnicode_Check(py_obj)) {
333*d3bd5b3dSLawrence D'Anna     PyObject *s = PyUnicode_AsUTF8String(py_obj);
334*d3bd5b3dSLawrence D'Anna     if (s == nullptr) {
335085328eeSLawrence D'Anna       PyErr_Clear();
336*d3bd5b3dSLawrence D'Anna       if (type == PyRefType::Owned)
337*d3bd5b3dSLawrence D'Anna         Py_DECREF(py_obj);
338*d3bd5b3dSLawrence D'Anna       return;
339*d3bd5b3dSLawrence D'Anna     }
340*d3bd5b3dSLawrence D'Anna     if (type == PyRefType::Owned)
341*d3bd5b3dSLawrence D'Anna       Py_DECREF(py_obj);
342*d3bd5b3dSLawrence D'Anna     else
343*d3bd5b3dSLawrence D'Anna       type = PyRefType::Owned;
344*d3bd5b3dSLawrence D'Anna     py_obj = s;
345085328eeSLawrence D'Anna   }
3467d6d218eSZachary Turner #endif
3472c1f46dcSZachary Turner }
3482c1f46dcSZachary Turner 
349b9c1b51eSKate Stone llvm::StringRef PythonString::GetString() const {
350085328eeSLawrence D'Anna   auto s = AsUTF8();
351085328eeSLawrence D'Anna   if (!s) {
352085328eeSLawrence D'Anna     llvm::consumeError(s.takeError());
353085328eeSLawrence D'Anna     return llvm::StringRef("");
354085328eeSLawrence D'Anna   }
355085328eeSLawrence D'Anna   return s.get();
356085328eeSLawrence D'Anna }
357085328eeSLawrence D'Anna 
358085328eeSLawrence D'Anna Expected<llvm::StringRef> PythonString::AsUTF8() const {
35918426935SZachary Turner   if (!IsValid())
360085328eeSLawrence D'Anna     return nullDeref();
36118426935SZachary Turner 
36222c8efcdSZachary Turner   Py_ssize_t size;
3635457b426SPavel Labath   const char *data;
36418426935SZachary Turner 
36518426935SZachary Turner #if PY_MAJOR_VERSION >= 3
3665457b426SPavel Labath   data = PyUnicode_AsUTF8AndSize(m_py_obj, &size);
36718426935SZachary Turner #else
368085328eeSLawrence D'Anna   char *c = NULL;
369085328eeSLawrence D'Anna   int r = PyString_AsStringAndSize(m_py_obj, &c, &size);
370085328eeSLawrence D'Anna   if (r < 0)
371085328eeSLawrence D'Anna     c = NULL;
3725457b426SPavel Labath   data = c;
37318426935SZachary Turner #endif
374085328eeSLawrence D'Anna 
375085328eeSLawrence D'Anna   if (!data)
376085328eeSLawrence D'Anna     return exception();
377085328eeSLawrence D'Anna 
3785457b426SPavel Labath   return llvm::StringRef(data, size);
37922c8efcdSZachary Turner }
3802c1f46dcSZachary Turner 
381b9c1b51eSKate Stone size_t PythonString::GetSize() const {
382b9c1b51eSKate Stone   if (IsValid()) {
38318426935SZachary Turner #if PY_MAJOR_VERSION >= 3
38418426935SZachary Turner     return PyUnicode_GetSize(m_py_obj);
38518426935SZachary Turner #else
38618426935SZachary Turner     return PyString_Size(m_py_obj);
38718426935SZachary Turner #endif
38818426935SZachary Turner   }
3892c1f46dcSZachary Turner   return 0;
3902c1f46dcSZachary Turner }
3912c1f46dcSZachary Turner 
392b9c1b51eSKate Stone void PythonString::SetString(llvm::StringRef string) {
393085328eeSLawrence D'Anna   auto s = FromUTF8(string);
394085328eeSLawrence D'Anna   if (!s) {
395085328eeSLawrence D'Anna     llvm::consumeError(s.takeError());
396085328eeSLawrence D'Anna     Reset();
397085328eeSLawrence D'Anna   } else {
398085328eeSLawrence D'Anna     PythonObject::Reset(std::move(s.get()));
399085328eeSLawrence D'Anna   }
4002c1f46dcSZachary Turner }
4012c1f46dcSZachary Turner 
402b9c1b51eSKate Stone StructuredData::StringSP PythonString::CreateStructuredString() const {
4032c1f46dcSZachary Turner   StructuredData::StringSP result(new StructuredData::String);
4042c1f46dcSZachary Turner   result->SetValue(GetString());
4052c1f46dcSZachary Turner   return result;
4062c1f46dcSZachary Turner }
4072c1f46dcSZachary Turner 
4082c1f46dcSZachary Turner // PythonInteger
4092c1f46dcSZachary Turner 
410*d3bd5b3dSLawrence D'Anna PythonInteger::PythonInteger(int64_t value) { SetInteger(value); }
4112c1f46dcSZachary Turner 
412b9c1b51eSKate Stone bool PythonInteger::Check(PyObject *py_obj) {
41322c8efcdSZachary Turner   if (!py_obj)
41422c8efcdSZachary Turner     return false;
41522c8efcdSZachary Turner 
41622c8efcdSZachary Turner #if PY_MAJOR_VERSION >= 3
41705097246SAdrian Prantl   // Python 3 does not have PyInt_Check.  There is only one type of integral
41805097246SAdrian Prantl   // value, long.
41922c8efcdSZachary Turner   return PyLong_Check(py_obj);
42022c8efcdSZachary Turner #else
42122c8efcdSZachary Turner   return PyLong_Check(py_obj) || PyInt_Check(py_obj);
42222c8efcdSZachary Turner #endif
4232c1f46dcSZachary Turner }
4242c1f46dcSZachary Turner 
425*d3bd5b3dSLawrence D'Anna void PythonInteger::Convert(PyRefType &type, PyObject *&py_obj) {
42622c8efcdSZachary Turner #if PY_MAJOR_VERSION < 3
42705097246SAdrian Prantl   // Always store this as a PyLong, which makes interoperability between Python
42805097246SAdrian Prantl   // 2.x and Python 3.x easier.  This is only necessary in 2.x, since 3.x
42905097246SAdrian Prantl   // doesn't even have a PyInt.
430b9c1b51eSKate Stone   if (PyInt_Check(py_obj)) {
431f8b22f8fSZachary Turner     // Since we converted the original object to a different type, the new
43205097246SAdrian Prantl     // object is an owned object regardless of the ownership semantics
43305097246SAdrian Prantl     // requested by the user.
434*d3bd5b3dSLawrence D'Anna     long long value = PyInt_AsLong(py_obj);
435*d3bd5b3dSLawrence D'Anna     PyObject *l = nullptr;
436*d3bd5b3dSLawrence D'Anna     if (!PyErr_Occurred())
437*d3bd5b3dSLawrence D'Anna       l = PyLong_FromLongLong(value);
438*d3bd5b3dSLawrence D'Anna     if (l == nullptr) {
439*d3bd5b3dSLawrence D'Anna       PyErr_Clear();
440*d3bd5b3dSLawrence D'Anna       if (type == PyRefType::Owned)
441*d3bd5b3dSLawrence D'Anna         Py_DECREF(py_obj);
442*d3bd5b3dSLawrence D'Anna       return;
443*d3bd5b3dSLawrence D'Anna     }
444*d3bd5b3dSLawrence D'Anna     if (type == PyRefType::Owned)
445*d3bd5b3dSLawrence D'Anna       Py_DECREF(py_obj);
446*d3bd5b3dSLawrence D'Anna     else
447*d3bd5b3dSLawrence D'Anna       type = PyRefType::Owned;
448*d3bd5b3dSLawrence D'Anna     py_obj = l;
44922c8efcdSZachary Turner   }
45022c8efcdSZachary Turner #endif
4512c1f46dcSZachary Turner }
4522c1f46dcSZachary Turner 
453b9c1b51eSKate Stone int64_t PythonInteger::GetInteger() const {
454b9c1b51eSKate Stone   if (m_py_obj) {
455b9c1b51eSKate Stone     assert(PyLong_Check(m_py_obj) &&
456b9c1b51eSKate Stone            "PythonInteger::GetInteger has a PyObject that isn't a PyLong");
45722c8efcdSZachary Turner 
458008ec446SGreg Clayton     int overflow = 0;
459008ec446SGreg Clayton     int64_t result = PyLong_AsLongLongAndOverflow(m_py_obj, &overflow);
460b9c1b51eSKate Stone     if (overflow != 0) {
46105097246SAdrian Prantl       // We got an integer that overflows, like 18446744072853913392L we can't
46205097246SAdrian Prantl       // use PyLong_AsLongLong() as it will return 0xffffffffffffffff. If we
46305097246SAdrian Prantl       // use the unsigned long long it will work as expected.
464008ec446SGreg Clayton       const uint64_t uval = PyLong_AsUnsignedLongLong(m_py_obj);
4654f730dc7SIlia K       result = static_cast<int64_t>(uval);
466008ec446SGreg Clayton     }
467008ec446SGreg Clayton     return result;
4682c1f46dcSZachary Turner   }
4692c1f46dcSZachary Turner   return UINT64_MAX;
4702c1f46dcSZachary Turner }
4712c1f46dcSZachary Turner 
472b9c1b51eSKate Stone void PythonInteger::SetInteger(int64_t value) {
473f8b22f8fSZachary Turner   PythonObject::Reset(PyRefType::Owned, PyLong_FromLongLong(value));
4742c1f46dcSZachary Turner }
4752c1f46dcSZachary Turner 
476b9c1b51eSKate Stone StructuredData::IntegerSP PythonInteger::CreateStructuredInteger() const {
4772c1f46dcSZachary Turner   StructuredData::IntegerSP result(new StructuredData::Integer);
4782c1f46dcSZachary Turner   result->SetValue(GetInteger());
4792c1f46dcSZachary Turner   return result;
4802c1f46dcSZachary Turner }
4812c1f46dcSZachary Turner 
482b81d715cSTatyana Krasnukha // PythonBoolean
483b81d715cSTatyana Krasnukha 
484b81d715cSTatyana Krasnukha PythonBoolean::PythonBoolean(bool value) {
485b81d715cSTatyana Krasnukha   SetValue(value);
486b81d715cSTatyana Krasnukha }
487b81d715cSTatyana Krasnukha 
488b81d715cSTatyana Krasnukha bool PythonBoolean::Check(PyObject *py_obj) {
489b81d715cSTatyana Krasnukha   return py_obj ? PyBool_Check(py_obj) : false;
490b81d715cSTatyana Krasnukha }
491b81d715cSTatyana Krasnukha 
492b81d715cSTatyana Krasnukha bool PythonBoolean::GetValue() const {
493b81d715cSTatyana Krasnukha   return m_py_obj ? PyObject_IsTrue(m_py_obj) : false;
494b81d715cSTatyana Krasnukha }
495b81d715cSTatyana Krasnukha 
496b81d715cSTatyana Krasnukha void PythonBoolean::SetValue(bool value) {
497b81d715cSTatyana Krasnukha   PythonObject::Reset(PyRefType::Owned, PyBool_FromLong(value));
498b81d715cSTatyana Krasnukha }
499b81d715cSTatyana Krasnukha 
500b81d715cSTatyana Krasnukha StructuredData::BooleanSP PythonBoolean::CreateStructuredBoolean() const {
501b81d715cSTatyana Krasnukha   StructuredData::BooleanSP result(new StructuredData::Boolean);
502b81d715cSTatyana Krasnukha   result->SetValue(GetValue());
503b81d715cSTatyana Krasnukha   return result;
504b81d715cSTatyana Krasnukha }
505b81d715cSTatyana Krasnukha 
5062c1f46dcSZachary Turner // PythonList
5072c1f46dcSZachary Turner 
508*d3bd5b3dSLawrence D'Anna PythonList::PythonList(PyInitialValue value) {
509f8b22f8fSZachary Turner   if (value == PyInitialValue::Empty)
510f8b22f8fSZachary Turner     Reset(PyRefType::Owned, PyList_New(0));
5112c1f46dcSZachary Turner }
5122c1f46dcSZachary Turner 
513*d3bd5b3dSLawrence D'Anna PythonList::PythonList(int list_size) {
51487f47729SZachary Turner   Reset(PyRefType::Owned, PyList_New(list_size));
51587f47729SZachary Turner }
51687f47729SZachary Turner 
517b9c1b51eSKate Stone bool PythonList::Check(PyObject *py_obj) {
51822c8efcdSZachary Turner   if (!py_obj)
51922c8efcdSZachary Turner     return false;
52022c8efcdSZachary Turner   return PyList_Check(py_obj);
52122c8efcdSZachary Turner }
52222c8efcdSZachary Turner 
523b9c1b51eSKate Stone uint32_t PythonList::GetSize() const {
524f8b22f8fSZachary Turner   if (IsValid())
5252c1f46dcSZachary Turner     return PyList_GET_SIZE(m_py_obj);
5262c1f46dcSZachary Turner   return 0;
5272c1f46dcSZachary Turner }
5282c1f46dcSZachary Turner 
529b9c1b51eSKate Stone PythonObject PythonList::GetItemAtIndex(uint32_t index) const {
530f8b22f8fSZachary Turner   if (IsValid())
531f8b22f8fSZachary Turner     return PythonObject(PyRefType::Borrowed, PyList_GetItem(m_py_obj, index));
5322c1f46dcSZachary Turner   return PythonObject();
5332c1f46dcSZachary Turner }
5342c1f46dcSZachary Turner 
535b9c1b51eSKate Stone void PythonList::SetItemAtIndex(uint32_t index, const PythonObject &object) {
536b9c1b51eSKate Stone   if (IsAllocated() && object.IsValid()) {
537f8b22f8fSZachary Turner     // PyList_SetItem is documented to "steal" a reference, so we need to
538f8b22f8fSZachary Turner     // convert it to an owned reference by incrementing it.
539f8b22f8fSZachary Turner     Py_INCREF(object.get());
5402c1f46dcSZachary Turner     PyList_SetItem(m_py_obj, index, object.get());
5412c1f46dcSZachary Turner   }
542f8b22f8fSZachary Turner }
5432c1f46dcSZachary Turner 
544b9c1b51eSKate Stone void PythonList::AppendItem(const PythonObject &object) {
545b9c1b51eSKate Stone   if (IsAllocated() && object.IsValid()) {
546f8b22f8fSZachary Turner     // `PyList_Append` does *not* steal a reference, so do not call `Py_INCREF`
547f8b22f8fSZachary Turner     // here like we do with `PyList_SetItem`.
5482c1f46dcSZachary Turner     PyList_Append(m_py_obj, object.get());
5492c1f46dcSZachary Turner   }
550f8b22f8fSZachary Turner }
5512c1f46dcSZachary Turner 
552b9c1b51eSKate Stone StructuredData::ArraySP PythonList::CreateStructuredArray() const {
5532c1f46dcSZachary Turner   StructuredData::ArraySP result(new StructuredData::Array);
5542c1f46dcSZachary Turner   uint32_t count = GetSize();
555b9c1b51eSKate Stone   for (uint32_t i = 0; i < count; ++i) {
5562c1f46dcSZachary Turner     PythonObject obj = GetItemAtIndex(i);
5572c1f46dcSZachary Turner     result->AddItem(obj.CreateStructuredObject());
5582c1f46dcSZachary Turner   }
5592c1f46dcSZachary Turner   return result;
5602c1f46dcSZachary Turner }
5612c1f46dcSZachary Turner 
562a1405147SZachary Turner // PythonTuple
563a1405147SZachary Turner 
564*d3bd5b3dSLawrence D'Anna PythonTuple::PythonTuple(PyInitialValue value) {
565a1405147SZachary Turner   if (value == PyInitialValue::Empty)
566a1405147SZachary Turner     Reset(PyRefType::Owned, PyTuple_New(0));
567a1405147SZachary Turner }
568a1405147SZachary Turner 
569*d3bd5b3dSLawrence D'Anna PythonTuple::PythonTuple(int tuple_size) {
570a1405147SZachary Turner   Reset(PyRefType::Owned, PyTuple_New(tuple_size));
571a1405147SZachary Turner }
572a1405147SZachary Turner 
573b9c1b51eSKate Stone PythonTuple::PythonTuple(std::initializer_list<PythonObject> objects) {
574a1405147SZachary Turner   m_py_obj = PyTuple_New(objects.size());
575a1405147SZachary Turner 
576a1405147SZachary Turner   uint32_t idx = 0;
577b9c1b51eSKate Stone   for (auto object : objects) {
578a1405147SZachary Turner     if (object.IsValid())
579a1405147SZachary Turner       SetItemAtIndex(idx, object);
580a1405147SZachary Turner     idx++;
581a1405147SZachary Turner   }
582a1405147SZachary Turner }
583a1405147SZachary Turner 
584b9c1b51eSKate Stone PythonTuple::PythonTuple(std::initializer_list<PyObject *> objects) {
585a1405147SZachary Turner   m_py_obj = PyTuple_New(objects.size());
586a1405147SZachary Turner 
587a1405147SZachary Turner   uint32_t idx = 0;
588b9c1b51eSKate Stone   for (auto py_object : objects) {
589a1405147SZachary Turner     PythonObject object(PyRefType::Borrowed, py_object);
590a1405147SZachary Turner     if (object.IsValid())
591a1405147SZachary Turner       SetItemAtIndex(idx, object);
592a1405147SZachary Turner     idx++;
593a1405147SZachary Turner   }
594a1405147SZachary Turner }
595a1405147SZachary Turner 
596b9c1b51eSKate Stone bool PythonTuple::Check(PyObject *py_obj) {
597a1405147SZachary Turner   if (!py_obj)
598a1405147SZachary Turner     return false;
599a1405147SZachary Turner   return PyTuple_Check(py_obj);
600a1405147SZachary Turner }
601a1405147SZachary Turner 
602b9c1b51eSKate Stone uint32_t PythonTuple::GetSize() const {
603a1405147SZachary Turner   if (IsValid())
604a1405147SZachary Turner     return PyTuple_GET_SIZE(m_py_obj);
605a1405147SZachary Turner   return 0;
606a1405147SZachary Turner }
607a1405147SZachary Turner 
608b9c1b51eSKate Stone PythonObject PythonTuple::GetItemAtIndex(uint32_t index) const {
609a1405147SZachary Turner   if (IsValid())
610a1405147SZachary Turner     return PythonObject(PyRefType::Borrowed, PyTuple_GetItem(m_py_obj, index));
611a1405147SZachary Turner   return PythonObject();
612a1405147SZachary Turner }
613a1405147SZachary Turner 
614b9c1b51eSKate Stone void PythonTuple::SetItemAtIndex(uint32_t index, const PythonObject &object) {
615b9c1b51eSKate Stone   if (IsAllocated() && object.IsValid()) {
616a1405147SZachary Turner     // PyTuple_SetItem is documented to "steal" a reference, so we need to
617a1405147SZachary Turner     // convert it to an owned reference by incrementing it.
618a1405147SZachary Turner     Py_INCREF(object.get());
619a1405147SZachary Turner     PyTuple_SetItem(m_py_obj, index, object.get());
620a1405147SZachary Turner   }
621a1405147SZachary Turner }
622a1405147SZachary Turner 
623b9c1b51eSKate Stone StructuredData::ArraySP PythonTuple::CreateStructuredArray() const {
624a1405147SZachary Turner   StructuredData::ArraySP result(new StructuredData::Array);
625a1405147SZachary Turner   uint32_t count = GetSize();
626b9c1b51eSKate Stone   for (uint32_t i = 0; i < count; ++i) {
627a1405147SZachary Turner     PythonObject obj = GetItemAtIndex(i);
628a1405147SZachary Turner     result->AddItem(obj.CreateStructuredObject());
629a1405147SZachary Turner   }
630a1405147SZachary Turner   return result;
631a1405147SZachary Turner }
632a1405147SZachary Turner 
6332c1f46dcSZachary Turner // PythonDictionary
6342c1f46dcSZachary Turner 
635*d3bd5b3dSLawrence D'Anna PythonDictionary::PythonDictionary(PyInitialValue value) {
636f8b22f8fSZachary Turner   if (value == PyInitialValue::Empty)
637f8b22f8fSZachary Turner     Reset(PyRefType::Owned, PyDict_New());
6382c1f46dcSZachary Turner }
6392c1f46dcSZachary Turner 
640b9c1b51eSKate Stone bool PythonDictionary::Check(PyObject *py_obj) {
64122c8efcdSZachary Turner   if (!py_obj)
64222c8efcdSZachary Turner     return false;
64322c8efcdSZachary Turner 
64422c8efcdSZachary Turner   return PyDict_Check(py_obj);
64522c8efcdSZachary Turner }
64622c8efcdSZachary Turner 
647b9c1b51eSKate Stone uint32_t PythonDictionary::GetSize() const {
648f8b22f8fSZachary Turner   if (IsValid())
6492c1f46dcSZachary Turner     return PyDict_Size(m_py_obj);
6502c1f46dcSZachary Turner   return 0;
6512c1f46dcSZachary Turner }
6522c1f46dcSZachary Turner 
653b9c1b51eSKate Stone PythonList PythonDictionary::GetKeys() const {
654f8b22f8fSZachary Turner   if (IsValid())
655f8b22f8fSZachary Turner     return PythonList(PyRefType::Owned, PyDict_Keys(m_py_obj));
656f8b22f8fSZachary Turner   return PythonList(PyInitialValue::Invalid);
6572c1f46dcSZachary Turner }
6582c1f46dcSZachary Turner 
659b9c1b51eSKate Stone PythonObject PythonDictionary::GetItemForKey(const PythonObject &key) const {
660f8b22f8fSZachary Turner   if (IsAllocated() && key.IsValid())
661b9c1b51eSKate Stone     return PythonObject(PyRefType::Borrowed,
662b9c1b51eSKate Stone                         PyDict_GetItem(m_py_obj, key.get()));
6632c1f46dcSZachary Turner   return PythonObject();
6642c1f46dcSZachary Turner }
6652c1f46dcSZachary Turner 
666b9c1b51eSKate Stone void PythonDictionary::SetItemForKey(const PythonObject &key,
667b9c1b51eSKate Stone                                      const PythonObject &value) {
668f8b22f8fSZachary Turner   if (IsAllocated() && key.IsValid() && value.IsValid())
6692c1f46dcSZachary Turner     PyDict_SetItem(m_py_obj, key.get(), value.get());
6702c1f46dcSZachary Turner }
6712c1f46dcSZachary Turner 
6722c1f46dcSZachary Turner StructuredData::DictionarySP
673b9c1b51eSKate Stone PythonDictionary::CreateStructuredDictionary() const {
6742c1f46dcSZachary Turner   StructuredData::DictionarySP result(new StructuredData::Dictionary);
6752c1f46dcSZachary Turner   PythonList keys(GetKeys());
6762c1f46dcSZachary Turner   uint32_t num_keys = keys.GetSize();
677b9c1b51eSKate Stone   for (uint32_t i = 0; i < num_keys; ++i) {
6782c1f46dcSZachary Turner     PythonObject key = keys.GetItemAtIndex(i);
6792c1f46dcSZachary Turner     PythonObject value = GetItemForKey(key);
6802c1f46dcSZachary Turner     StructuredData::ObjectSP structured_value = value.CreateStructuredObject();
681f8b22f8fSZachary Turner     result->AddItem(key.Str().GetString(), structured_value);
6822c1f46dcSZachary Turner   }
6832c1f46dcSZachary Turner   return result;
6842c1f46dcSZachary Turner }
6852c1f46dcSZachary Turner 
686b9c1b51eSKate Stone PythonModule PythonModule::BuiltinsModule() {
687a1405147SZachary Turner #if PY_MAJOR_VERSION >= 3
688a1405147SZachary Turner   return AddModule("builtins");
689a1405147SZachary Turner #else
690a1405147SZachary Turner   return AddModule("__builtin__");
691a1405147SZachary Turner #endif
692a1405147SZachary Turner }
693a1405147SZachary Turner 
694b9c1b51eSKate Stone PythonModule PythonModule::MainModule() { return AddModule("__main__"); }
695a1405147SZachary Turner 
696b9c1b51eSKate Stone PythonModule PythonModule::AddModule(llvm::StringRef module) {
697a1405147SZachary Turner   std::string str = module.str();
698a1405147SZachary Turner   return PythonModule(PyRefType::Borrowed, PyImport_AddModule(str.c_str()));
6997841efbbSZachary Turner }
7007841efbbSZachary Turner 
701085328eeSLawrence D'Anna Expected<PythonModule> PythonModule::Import(const char *name) {
702085328eeSLawrence D'Anna   PyObject *mod = PyImport_ImportModule(name);
703085328eeSLawrence D'Anna   if (!mod)
704085328eeSLawrence D'Anna     return exception();
705085328eeSLawrence D'Anna   return Take<PythonModule>(mod);
706085328eeSLawrence D'Anna }
707085328eeSLawrence D'Anna 
708085328eeSLawrence D'Anna Expected<PythonObject> PythonModule::Get(const char *name) {
709085328eeSLawrence D'Anna   if (!IsValid())
710085328eeSLawrence D'Anna     return nullDeref();
711085328eeSLawrence D'Anna   PyObject *dict = PyModule_GetDict(m_py_obj);
712085328eeSLawrence D'Anna   if (!dict)
713085328eeSLawrence D'Anna     return exception();
714085328eeSLawrence D'Anna   PyObject *item = PyDict_GetItemString(dict, name);
715085328eeSLawrence D'Anna   if (!item)
716085328eeSLawrence D'Anna     return exception();
717085328eeSLawrence D'Anna   return Retain<PythonObject>(item);
7182419f1d5SZachary Turner }
7192419f1d5SZachary Turner 
720b9c1b51eSKate Stone bool PythonModule::Check(PyObject *py_obj) {
7217841efbbSZachary Turner   if (!py_obj)
7227841efbbSZachary Turner     return false;
7237841efbbSZachary Turner 
7247841efbbSZachary Turner   return PyModule_Check(py_obj);
7257841efbbSZachary Turner }
7267841efbbSZachary Turner 
727b9c1b51eSKate Stone PythonDictionary PythonModule::GetDictionary() const {
7287841efbbSZachary Turner   return PythonDictionary(PyRefType::Borrowed, PyModule_GetDict(m_py_obj));
7297841efbbSZachary Turner }
7307841efbbSZachary Turner 
731b9c1b51eSKate Stone bool PythonCallable::Check(PyObject *py_obj) {
732a1405147SZachary Turner   if (!py_obj)
733a1405147SZachary Turner     return false;
734a1405147SZachary Turner 
735a1405147SZachary Turner   return PyCallable_Check(py_obj);
736a1405147SZachary Turner }
737a1405147SZachary Turner 
73827a14f19SJim Ingham PythonCallable::ArgInfo PythonCallable::GetNumInitArguments() const {
73927a14f19SJim Ingham   ArgInfo result = {0, false, false, false};
74027a14f19SJim Ingham   if (!IsValid())
74127a14f19SJim Ingham     return result;
74227a14f19SJim Ingham 
74327a14f19SJim Ingham   PythonObject __init__ = GetAttributeValue("__init__");
74427a14f19SJim Ingham   if (__init__.IsValid() ) {
74527a14f19SJim Ingham     auto __init_callable__ = __init__.AsType<PythonCallable>();
74627a14f19SJim Ingham     if (__init_callable__.IsValid())
74727a14f19SJim Ingham       return __init_callable__.GetNumArguments();
74827a14f19SJim Ingham   }
74927a14f19SJim Ingham   return result;
75027a14f19SJim Ingham }
75127a14f19SJim Ingham 
752b9c1b51eSKate Stone PythonCallable::ArgInfo PythonCallable::GetNumArguments() const {
753a5d6765cSEnrico Granata   ArgInfo result = {0, false, false, false};
754a1405147SZachary Turner   if (!IsValid())
755b58fb2f4SZachary Turner     return result;
756a1405147SZachary Turner 
757a1405147SZachary Turner   PyObject *py_func_obj = m_py_obj;
758b9c1b51eSKate Stone   if (PyMethod_Check(py_func_obj)) {
759a1405147SZachary Turner     py_func_obj = PyMethod_GET_FUNCTION(py_func_obj);
760a5d6765cSEnrico Granata     PythonObject im_self = GetAttributeValue("im_self");
761a5d6765cSEnrico Granata     if (im_self.IsValid() && !im_self.IsNone())
762a5d6765cSEnrico Granata       result.is_bound_method = true;
763b9c1b51eSKate Stone   } else {
764a5d6765cSEnrico Granata     // see if this is a callable object with an __call__ method
765b9c1b51eSKate Stone     if (!PyFunction_Check(py_func_obj)) {
766a5d6765cSEnrico Granata       PythonObject __call__ = GetAttributeValue("__call__");
767b9c1b51eSKate Stone       if (__call__.IsValid()) {
768a5d6765cSEnrico Granata         auto __callable__ = __call__.AsType<PythonCallable>();
769b9c1b51eSKate Stone         if (__callable__.IsValid()) {
770a5d6765cSEnrico Granata           py_func_obj = PyMethod_GET_FUNCTION(__callable__.get());
771a5d6765cSEnrico Granata           PythonObject im_self = GetAttributeValue("im_self");
772a5d6765cSEnrico Granata           if (im_self.IsValid() && !im_self.IsNone())
773a5d6765cSEnrico Granata             result.is_bound_method = true;
774a5d6765cSEnrico Granata         }
775a5d6765cSEnrico Granata       }
776a5d6765cSEnrico Granata     }
777a5d6765cSEnrico Granata   }
778a1405147SZachary Turner 
779a1405147SZachary Turner   if (!py_func_obj)
780b58fb2f4SZachary Turner     return result;
781a1405147SZachary Turner 
782a1405147SZachary Turner   PyCodeObject *code = (PyCodeObject *)PyFunction_GET_CODE(py_func_obj);
783a1405147SZachary Turner   if (!code)
784b58fb2f4SZachary Turner     return result;
785a1405147SZachary Turner 
786b58fb2f4SZachary Turner   result.count = code->co_argcount;
787b58fb2f4SZachary Turner   result.has_varargs = !!(code->co_flags & CO_VARARGS);
788b58fb2f4SZachary Turner   result.has_kwargs = !!(code->co_flags & CO_VARKEYWORDS);
789b58fb2f4SZachary Turner   return result;
790b58fb2f4SZachary Turner }
791b58fb2f4SZachary Turner 
792b9c1b51eSKate Stone PythonObject PythonCallable::operator()() {
793b9c1b51eSKate Stone   return PythonObject(PyRefType::Owned, PyObject_CallObject(m_py_obj, nullptr));
794a1405147SZachary Turner }
795a1405147SZachary Turner 
796b9c1b51eSKate Stone PythonObject PythonCallable::
797b9c1b51eSKate Stone operator()(std::initializer_list<PyObject *> args) {
798a1405147SZachary Turner   PythonTuple arg_tuple(args);
799a1405147SZachary Turner   return PythonObject(PyRefType::Owned,
800a1405147SZachary Turner                       PyObject_CallObject(m_py_obj, arg_tuple.get()));
801a1405147SZachary Turner }
802a1405147SZachary Turner 
803b9c1b51eSKate Stone PythonObject PythonCallable::
804b9c1b51eSKate Stone operator()(std::initializer_list<PythonObject> args) {
805a1405147SZachary Turner   PythonTuple arg_tuple(args);
806a1405147SZachary Turner   return PythonObject(PyRefType::Owned,
807a1405147SZachary Turner                       PyObject_CallObject(m_py_obj, arg_tuple.get()));
808a1405147SZachary Turner }
809a1405147SZachary Turner 
810b9c1b51eSKate Stone bool PythonFile::Check(PyObject *py_obj) {
81196898eb6SLawrence D'Anna   if (!py_obj)
81296898eb6SLawrence D'Anna     return false;
8139c40264fSZachary Turner #if PY_MAJOR_VERSION < 3
81423502721SJason Molenda   return PyFile_Check(py_obj);
81523502721SJason Molenda #else
8169c40264fSZachary Turner   // In Python 3, there is no `PyFile_Check`, and in fact PyFile is not even a
8179c40264fSZachary Turner   // first-class object type anymore.  `PyFile_FromFd` is just a thin wrapper
81805097246SAdrian Prantl   // over `io.open()`, which returns some object derived from `io.IOBase`. As a
81905097246SAdrian Prantl   // result, the only way to detect a file in Python 3 is to check whether it
82021b8a8aeSLawrence D'Anna   // inherits from `io.IOBase`.
82121b8a8aeSLawrence D'Anna   auto io_module = PythonModule::Import("io");
82221b8a8aeSLawrence D'Anna   if (!io_module) {
82321b8a8aeSLawrence D'Anna     llvm::consumeError(io_module.takeError());
8249c40264fSZachary Turner     return false;
82521b8a8aeSLawrence D'Anna   }
82621b8a8aeSLawrence D'Anna   auto iobase = io_module.get().Get("IOBase");
82721b8a8aeSLawrence D'Anna   if (!iobase) {
82821b8a8aeSLawrence D'Anna     llvm::consumeError(iobase.takeError());
8299c40264fSZachary Turner     return false;
83021b8a8aeSLawrence D'Anna   }
83121b8a8aeSLawrence D'Anna   int r = PyObject_IsInstance(py_obj, iobase.get().get());
83221b8a8aeSLawrence D'Anna   if (r < 0) {
83321b8a8aeSLawrence D'Anna     llvm::consumeError(exception()); // clear the exception and log it.
83421b8a8aeSLawrence D'Anna     return false;
83521b8a8aeSLawrence D'Anna   }
83621b8a8aeSLawrence D'Anna   return !!r;
83723502721SJason Molenda #endif
8389c40264fSZachary Turner }
8399c40264fSZachary Turner 
8402fce1137SLawrence D'Anna FileUP PythonFile::GetUnderlyingFile() const {
841eda01c31SZachary Turner   if (!IsValid())
8422fce1137SLawrence D'Anna     return nullptr;
843eda01c31SZachary Turner 
844eda01c31SZachary Turner   // We don't own the file descriptor returned by this function, make sure the
845eda01c31SZachary Turner   // File object knows about that.
846744959b9SEnrico Granata   PythonString py_mode = GetAttributeValue("mode").AsType<PythonString>();
84757504530SLawrence D'Anna   auto options = File::GetOptionsFromMode(py_mode.GetString());
84862c9fe42SLawrence D'Anna   if (!options) {
84962c9fe42SLawrence D'Anna     llvm::consumeError(options.takeError());
85062c9fe42SLawrence D'Anna     return nullptr;
85162c9fe42SLawrence D'Anna   }
85262c9fe42SLawrence D'Anna   auto file = std::unique_ptr<File>(new NativeFile(
85362c9fe42SLawrence D'Anna       PyObject_AsFileDescriptor(m_py_obj), options.get(), false));
8542fce1137SLawrence D'Anna   if (!file->IsValid())
8552fce1137SLawrence D'Anna     return nullptr;
8562fce1137SLawrence D'Anna   return file;
857eda01c31SZachary Turner }
858d68983e3SPavel Labath 
85921b8a8aeSLawrence D'Anna namespace {
86021b8a8aeSLawrence D'Anna class GIL {
86121b8a8aeSLawrence D'Anna public:
86221b8a8aeSLawrence D'Anna   GIL() {
86321b8a8aeSLawrence D'Anna     m_state = PyGILState_Ensure();
86421b8a8aeSLawrence D'Anna     assert(!PyErr_Occurred());
86521b8a8aeSLawrence D'Anna   }
86621b8a8aeSLawrence D'Anna   ~GIL() { PyGILState_Release(m_state); }
86721b8a8aeSLawrence D'Anna 
86821b8a8aeSLawrence D'Anna protected:
86921b8a8aeSLawrence D'Anna   PyGILState_STATE m_state;
87021b8a8aeSLawrence D'Anna };
87121b8a8aeSLawrence D'Anna } // namespace
87221b8a8aeSLawrence D'Anna 
873085328eeSLawrence D'Anna const char *PythonException::toCString() const {
874085328eeSLawrence D'Anna   if (!m_repr_bytes)
875085328eeSLawrence D'Anna     return "unknown exception";
876085328eeSLawrence D'Anna   return PyBytes_AS_STRING(m_repr_bytes);
877085328eeSLawrence D'Anna }
878085328eeSLawrence D'Anna 
879085328eeSLawrence D'Anna PythonException::PythonException(const char *caller) {
880085328eeSLawrence D'Anna   assert(PyErr_Occurred());
881085328eeSLawrence D'Anna   m_exception_type = m_exception = m_traceback = m_repr_bytes = NULL;
882085328eeSLawrence D'Anna   PyErr_Fetch(&m_exception_type, &m_exception, &m_traceback);
883085328eeSLawrence D'Anna   PyErr_NormalizeException(&m_exception_type, &m_exception, &m_traceback);
884085328eeSLawrence D'Anna   PyErr_Clear();
885085328eeSLawrence D'Anna   if (m_exception) {
886085328eeSLawrence D'Anna     PyObject *repr = PyObject_Repr(m_exception);
887085328eeSLawrence D'Anna     if (repr) {
888085328eeSLawrence D'Anna       m_repr_bytes = PyUnicode_AsEncodedString(repr, "utf-8", nullptr);
889085328eeSLawrence D'Anna       if (!m_repr_bytes) {
890085328eeSLawrence D'Anna         PyErr_Clear();
891085328eeSLawrence D'Anna       }
892085328eeSLawrence D'Anna       Py_XDECREF(repr);
893085328eeSLawrence D'Anna     } else {
894085328eeSLawrence D'Anna       PyErr_Clear();
895085328eeSLawrence D'Anna     }
896085328eeSLawrence D'Anna   }
897085328eeSLawrence D'Anna   Log *log = GetLogIfAllCategoriesSet(LIBLLDB_LOG_SCRIPT);
898085328eeSLawrence D'Anna   if (caller)
899085328eeSLawrence D'Anna     LLDB_LOGF(log, "%s failed with exception: %s", caller, toCString());
900085328eeSLawrence D'Anna   else
901085328eeSLawrence D'Anna     LLDB_LOGF(log, "python exception: %s", toCString());
902085328eeSLawrence D'Anna }
903085328eeSLawrence D'Anna void PythonException::Restore() {
904085328eeSLawrence D'Anna   if (m_exception_type && m_exception) {
905085328eeSLawrence D'Anna     PyErr_Restore(m_exception_type, m_exception, m_traceback);
906085328eeSLawrence D'Anna   } else {
907085328eeSLawrence D'Anna     PyErr_SetString(PyExc_Exception, toCString());
908085328eeSLawrence D'Anna   }
909085328eeSLawrence D'Anna   m_exception_type = m_exception = m_traceback = NULL;
910085328eeSLawrence D'Anna }
911085328eeSLawrence D'Anna 
912085328eeSLawrence D'Anna PythonException::~PythonException() {
913085328eeSLawrence D'Anna   Py_XDECREF(m_exception_type);
914085328eeSLawrence D'Anna   Py_XDECREF(m_exception);
915085328eeSLawrence D'Anna   Py_XDECREF(m_traceback);
916085328eeSLawrence D'Anna   Py_XDECREF(m_repr_bytes);
917085328eeSLawrence D'Anna }
918085328eeSLawrence D'Anna 
919085328eeSLawrence D'Anna void PythonException::log(llvm::raw_ostream &OS) const { OS << toCString(); }
920085328eeSLawrence D'Anna 
921085328eeSLawrence D'Anna std::error_code PythonException::convertToErrorCode() const {
922085328eeSLawrence D'Anna   return llvm::inconvertibleErrorCode();
923085328eeSLawrence D'Anna }
924085328eeSLawrence D'Anna 
925085328eeSLawrence D'Anna char PythonException::ID = 0;
926085328eeSLawrence D'Anna 
92762c9fe42SLawrence D'Anna llvm::Expected<File::OpenOptions>
92862c9fe42SLawrence D'Anna GetOptionsForPyObject(const PythonObject &obj) {
92921b8a8aeSLawrence D'Anna #if PY_MAJOR_VERSION >= 3
93062c9fe42SLawrence D'Anna   auto options = File::OpenOptions(0);
93121b8a8aeSLawrence D'Anna   auto readable = As<bool>(obj.CallMethod("readable"));
93221b8a8aeSLawrence D'Anna   if (!readable)
93321b8a8aeSLawrence D'Anna     return readable.takeError();
93421b8a8aeSLawrence D'Anna   auto writable = As<bool>(obj.CallMethod("writable"));
93521b8a8aeSLawrence D'Anna   if (!writable)
93621b8a8aeSLawrence D'Anna     return writable.takeError();
93721b8a8aeSLawrence D'Anna   if (readable.get())
93821b8a8aeSLawrence D'Anna     options |= File::eOpenOptionRead;
93921b8a8aeSLawrence D'Anna   if (writable.get())
94021b8a8aeSLawrence D'Anna     options |= File::eOpenOptionWrite;
94162c9fe42SLawrence D'Anna   return options;
94221b8a8aeSLawrence D'Anna #else
94321b8a8aeSLawrence D'Anna   PythonString py_mode = obj.GetAttributeValue("mode").AsType<PythonString>();
94462c9fe42SLawrence D'Anna   return File::GetOptionsFromMode(py_mode.GetString());
94521b8a8aeSLawrence D'Anna #endif
94621b8a8aeSLawrence D'Anna }
94721b8a8aeSLawrence D'Anna 
94821b8a8aeSLawrence D'Anna // Base class template for python files.   All it knows how to do
94921b8a8aeSLawrence D'Anna // is hold a reference to the python object and close or flush it
95021b8a8aeSLawrence D'Anna // when the File is closed.
95121b8a8aeSLawrence D'Anna namespace {
95221b8a8aeSLawrence D'Anna template <typename Base> class OwnedPythonFile : public Base {
95321b8a8aeSLawrence D'Anna public:
95421b8a8aeSLawrence D'Anna   template <typename... Args>
95521b8a8aeSLawrence D'Anna   OwnedPythonFile(const PythonFile &file, bool borrowed, Args... args)
95621b8a8aeSLawrence D'Anna       : Base(args...), m_py_obj(file), m_borrowed(borrowed) {
95721b8a8aeSLawrence D'Anna     assert(m_py_obj);
95821b8a8aeSLawrence D'Anna   }
95921b8a8aeSLawrence D'Anna 
96021b8a8aeSLawrence D'Anna   ~OwnedPythonFile() override {
96121b8a8aeSLawrence D'Anna     assert(m_py_obj);
96221b8a8aeSLawrence D'Anna     GIL takeGIL;
96321b8a8aeSLawrence D'Anna     Close();
96421b8a8aeSLawrence D'Anna     m_py_obj.Reset();
96521b8a8aeSLawrence D'Anna   }
96621b8a8aeSLawrence D'Anna 
96721b8a8aeSLawrence D'Anna   bool IsPythonSideValid() const {
96821b8a8aeSLawrence D'Anna     GIL takeGIL;
96921b8a8aeSLawrence D'Anna     auto closed = As<bool>(m_py_obj.GetAttribute("closed"));
97021b8a8aeSLawrence D'Anna     if (!closed) {
97121b8a8aeSLawrence D'Anna       llvm::consumeError(closed.takeError());
97221b8a8aeSLawrence D'Anna       return false;
97321b8a8aeSLawrence D'Anna     }
97421b8a8aeSLawrence D'Anna     return !closed.get();
97521b8a8aeSLawrence D'Anna   }
97621b8a8aeSLawrence D'Anna 
97721b8a8aeSLawrence D'Anna   bool IsValid() const override {
97821b8a8aeSLawrence D'Anna     return IsPythonSideValid() && Base::IsValid();
97921b8a8aeSLawrence D'Anna   }
98021b8a8aeSLawrence D'Anna 
98121b8a8aeSLawrence D'Anna   Status Close() override {
98221b8a8aeSLawrence D'Anna     assert(m_py_obj);
98321b8a8aeSLawrence D'Anna     Status py_error, base_error;
98421b8a8aeSLawrence D'Anna     GIL takeGIL;
98521b8a8aeSLawrence D'Anna     if (!m_borrowed) {
98621b8a8aeSLawrence D'Anna       auto r = m_py_obj.CallMethod("close");
98721b8a8aeSLawrence D'Anna       if (!r)
98821b8a8aeSLawrence D'Anna         py_error = Status(r.takeError());
98921b8a8aeSLawrence D'Anna     }
99021b8a8aeSLawrence D'Anna     base_error = Base::Close();
99121b8a8aeSLawrence D'Anna     if (py_error.Fail())
99221b8a8aeSLawrence D'Anna       return py_error;
99321b8a8aeSLawrence D'Anna     return base_error;
99421b8a8aeSLawrence D'Anna   };
99521b8a8aeSLawrence D'Anna 
996d9b553ecSLawrence D'Anna   PyObject *GetPythonObject() const {
997d9b553ecSLawrence D'Anna     assert(m_py_obj.IsValid());
998d9b553ecSLawrence D'Anna     return m_py_obj.get();
999d9b553ecSLawrence D'Anna   }
1000d9b553ecSLawrence D'Anna 
1001d9b553ecSLawrence D'Anna   static bool classof(const File *file) = delete;
1002d9b553ecSLawrence D'Anna 
100321b8a8aeSLawrence D'Anna protected:
100421b8a8aeSLawrence D'Anna   PythonFile m_py_obj;
100521b8a8aeSLawrence D'Anna   bool m_borrowed;
100621b8a8aeSLawrence D'Anna };
100721b8a8aeSLawrence D'Anna } // namespace
100821b8a8aeSLawrence D'Anna 
100921b8a8aeSLawrence D'Anna // A SimplePythonFile is a OwnedPythonFile that just does all I/O as
101021b8a8aeSLawrence D'Anna // a NativeFile
101121b8a8aeSLawrence D'Anna namespace {
101221b8a8aeSLawrence D'Anna class SimplePythonFile : public OwnedPythonFile<NativeFile> {
101321b8a8aeSLawrence D'Anna public:
101421b8a8aeSLawrence D'Anna   SimplePythonFile(const PythonFile &file, bool borrowed, int fd,
101562c9fe42SLawrence D'Anna                    File::OpenOptions options)
101621b8a8aeSLawrence D'Anna       : OwnedPythonFile(file, borrowed, fd, options, false) {}
1017d9b553ecSLawrence D'Anna 
1018d9b553ecSLawrence D'Anna   static char ID;
1019d9b553ecSLawrence D'Anna   bool isA(const void *classID) const override {
1020d9b553ecSLawrence D'Anna     return classID == &ID || NativeFile::isA(classID);
1021d9b553ecSLawrence D'Anna   }
1022d9b553ecSLawrence D'Anna   static bool classof(const File *file) { return file->isA(&ID); }
102321b8a8aeSLawrence D'Anna };
1024d9b553ecSLawrence D'Anna char SimplePythonFile::ID = 0;
102521b8a8aeSLawrence D'Anna } // namespace
102621b8a8aeSLawrence D'Anna 
102721b8a8aeSLawrence D'Anna #if PY_MAJOR_VERSION >= 3
102821b8a8aeSLawrence D'Anna 
102921b8a8aeSLawrence D'Anna namespace {
103021b8a8aeSLawrence D'Anna class PythonBuffer {
103121b8a8aeSLawrence D'Anna public:
103221b8a8aeSLawrence D'Anna   PythonBuffer &operator=(const PythonBuffer &) = delete;
103321b8a8aeSLawrence D'Anna   PythonBuffer(const PythonBuffer &) = delete;
103421b8a8aeSLawrence D'Anna 
103521b8a8aeSLawrence D'Anna   static Expected<PythonBuffer> Create(PythonObject &obj,
103621b8a8aeSLawrence D'Anna                                        int flags = PyBUF_SIMPLE) {
103721b8a8aeSLawrence D'Anna     Py_buffer py_buffer = {};
103821b8a8aeSLawrence D'Anna     PyObject_GetBuffer(obj.get(), &py_buffer, flags);
103921b8a8aeSLawrence D'Anna     if (!py_buffer.obj)
104021b8a8aeSLawrence D'Anna       return llvm::make_error<PythonException>();
104121b8a8aeSLawrence D'Anna     return PythonBuffer(py_buffer);
104221b8a8aeSLawrence D'Anna   }
104321b8a8aeSLawrence D'Anna 
104421b8a8aeSLawrence D'Anna   PythonBuffer(PythonBuffer &&other) {
104521b8a8aeSLawrence D'Anna     m_buffer = other.m_buffer;
104621b8a8aeSLawrence D'Anna     other.m_buffer.obj = nullptr;
104721b8a8aeSLawrence D'Anna   }
104821b8a8aeSLawrence D'Anna 
104921b8a8aeSLawrence D'Anna   ~PythonBuffer() {
105021b8a8aeSLawrence D'Anna     if (m_buffer.obj)
105121b8a8aeSLawrence D'Anna       PyBuffer_Release(&m_buffer);
105221b8a8aeSLawrence D'Anna   }
105321b8a8aeSLawrence D'Anna 
105421b8a8aeSLawrence D'Anna   Py_buffer &get() { return m_buffer; }
105521b8a8aeSLawrence D'Anna 
105621b8a8aeSLawrence D'Anna private:
105721b8a8aeSLawrence D'Anna   // takes ownership of the buffer.
105821b8a8aeSLawrence D'Anna   PythonBuffer(const Py_buffer &py_buffer) : m_buffer(py_buffer) {}
105921b8a8aeSLawrence D'Anna   Py_buffer m_buffer;
106021b8a8aeSLawrence D'Anna };
106121b8a8aeSLawrence D'Anna } // namespace
106221b8a8aeSLawrence D'Anna 
106321b8a8aeSLawrence D'Anna // Shared methods between TextPythonFile and BinaryPythonFile
106421b8a8aeSLawrence D'Anna namespace {
106521b8a8aeSLawrence D'Anna class PythonIOFile : public OwnedPythonFile<File> {
106621b8a8aeSLawrence D'Anna public:
106721b8a8aeSLawrence D'Anna   PythonIOFile(const PythonFile &file, bool borrowed)
106821b8a8aeSLawrence D'Anna       : OwnedPythonFile(file, borrowed) {}
106921b8a8aeSLawrence D'Anna 
107021b8a8aeSLawrence D'Anna   ~PythonIOFile() override { Close(); }
107121b8a8aeSLawrence D'Anna 
107221b8a8aeSLawrence D'Anna   bool IsValid() const override { return IsPythonSideValid(); }
107321b8a8aeSLawrence D'Anna 
107421b8a8aeSLawrence D'Anna   Status Close() override {
107521b8a8aeSLawrence D'Anna     assert(m_py_obj);
107621b8a8aeSLawrence D'Anna     GIL takeGIL;
107721b8a8aeSLawrence D'Anna     if (m_borrowed)
107821b8a8aeSLawrence D'Anna       return Flush();
107921b8a8aeSLawrence D'Anna     auto r = m_py_obj.CallMethod("close");
108021b8a8aeSLawrence D'Anna     if (!r)
108121b8a8aeSLawrence D'Anna       return Status(r.takeError());
108221b8a8aeSLawrence D'Anna     return Status();
108321b8a8aeSLawrence D'Anna   }
108421b8a8aeSLawrence D'Anna 
108521b8a8aeSLawrence D'Anna   Status Flush() override {
108621b8a8aeSLawrence D'Anna     GIL takeGIL;
108721b8a8aeSLawrence D'Anna     auto r = m_py_obj.CallMethod("flush");
108821b8a8aeSLawrence D'Anna     if (!r)
108921b8a8aeSLawrence D'Anna       return Status(r.takeError());
109021b8a8aeSLawrence D'Anna     return Status();
109121b8a8aeSLawrence D'Anna   }
109221b8a8aeSLawrence D'Anna 
1093d9b553ecSLawrence D'Anna   Expected<File::OpenOptions> GetOptions() const override {
1094d9b553ecSLawrence D'Anna     GIL takeGIL;
1095d9b553ecSLawrence D'Anna     return GetOptionsForPyObject(m_py_obj);
1096d9b553ecSLawrence D'Anna   }
1097d9b553ecSLawrence D'Anna 
1098d9b553ecSLawrence D'Anna   static char ID;
1099d9b553ecSLawrence D'Anna   bool isA(const void *classID) const override {
1100d9b553ecSLawrence D'Anna     return classID == &ID || File::isA(classID);
1101d9b553ecSLawrence D'Anna   }
1102d9b553ecSLawrence D'Anna   static bool classof(const File *file) { return file->isA(&ID); }
110321b8a8aeSLawrence D'Anna };
1104d9b553ecSLawrence D'Anna char PythonIOFile::ID = 0;
110521b8a8aeSLawrence D'Anna } // namespace
110621b8a8aeSLawrence D'Anna 
110721b8a8aeSLawrence D'Anna namespace {
110821b8a8aeSLawrence D'Anna class BinaryPythonFile : public PythonIOFile {
110921b8a8aeSLawrence D'Anna protected:
111021b8a8aeSLawrence D'Anna   int m_descriptor;
111121b8a8aeSLawrence D'Anna 
111221b8a8aeSLawrence D'Anna public:
111321b8a8aeSLawrence D'Anna   BinaryPythonFile(int fd, const PythonFile &file, bool borrowed)
111421b8a8aeSLawrence D'Anna       : PythonIOFile(file, borrowed),
111521b8a8aeSLawrence D'Anna         m_descriptor(File::DescriptorIsValid(fd) ? fd
111621b8a8aeSLawrence D'Anna                                                  : File::kInvalidDescriptor) {}
111721b8a8aeSLawrence D'Anna 
111821b8a8aeSLawrence D'Anna   int GetDescriptor() const override { return m_descriptor; }
111921b8a8aeSLawrence D'Anna 
112021b8a8aeSLawrence D'Anna   Status Write(const void *buf, size_t &num_bytes) override {
112121b8a8aeSLawrence D'Anna     GIL takeGIL;
112221b8a8aeSLawrence D'Anna     PyObject *pybuffer_p = PyMemoryView_FromMemory(
112321b8a8aeSLawrence D'Anna         const_cast<char *>((const char *)buf), num_bytes, PyBUF_READ);
112421b8a8aeSLawrence D'Anna     if (!pybuffer_p)
112521b8a8aeSLawrence D'Anna       return Status(llvm::make_error<PythonException>());
112621b8a8aeSLawrence D'Anna     auto pybuffer = Take<PythonObject>(pybuffer_p);
112721b8a8aeSLawrence D'Anna     num_bytes = 0;
112821b8a8aeSLawrence D'Anna     auto bytes_written = As<long long>(m_py_obj.CallMethod("write", pybuffer));
112921b8a8aeSLawrence D'Anna     if (!bytes_written)
113021b8a8aeSLawrence D'Anna       return Status(bytes_written.takeError());
113121b8a8aeSLawrence D'Anna     if (bytes_written.get() < 0)
113221b8a8aeSLawrence D'Anna       return Status(".write() method returned a negative number!");
113321b8a8aeSLawrence D'Anna     static_assert(sizeof(long long) >= sizeof(size_t), "overflow");
113421b8a8aeSLawrence D'Anna     num_bytes = bytes_written.get();
113521b8a8aeSLawrence D'Anna     return Status();
113621b8a8aeSLawrence D'Anna   }
113721b8a8aeSLawrence D'Anna 
113821b8a8aeSLawrence D'Anna   Status Read(void *buf, size_t &num_bytes) override {
113921b8a8aeSLawrence D'Anna     GIL takeGIL;
114021b8a8aeSLawrence D'Anna     static_assert(sizeof(long long) >= sizeof(size_t), "overflow");
114121b8a8aeSLawrence D'Anna     auto pybuffer_obj =
114221b8a8aeSLawrence D'Anna         m_py_obj.CallMethod("read", (unsigned long long)num_bytes);
114321b8a8aeSLawrence D'Anna     if (!pybuffer_obj)
114421b8a8aeSLawrence D'Anna       return Status(pybuffer_obj.takeError());
114521b8a8aeSLawrence D'Anna     num_bytes = 0;
114621b8a8aeSLawrence D'Anna     if (pybuffer_obj.get().IsNone()) {
114721b8a8aeSLawrence D'Anna       // EOF
114821b8a8aeSLawrence D'Anna       num_bytes = 0;
114921b8a8aeSLawrence D'Anna       return Status();
115021b8a8aeSLawrence D'Anna     }
115121b8a8aeSLawrence D'Anna     auto pybuffer = PythonBuffer::Create(pybuffer_obj.get());
115221b8a8aeSLawrence D'Anna     if (!pybuffer)
115321b8a8aeSLawrence D'Anna       return Status(pybuffer.takeError());
115421b8a8aeSLawrence D'Anna     memcpy(buf, pybuffer.get().get().buf, pybuffer.get().get().len);
115521b8a8aeSLawrence D'Anna     num_bytes = pybuffer.get().get().len;
115621b8a8aeSLawrence D'Anna     return Status();
115721b8a8aeSLawrence D'Anna   }
115821b8a8aeSLawrence D'Anna };
115921b8a8aeSLawrence D'Anna } // namespace
116021b8a8aeSLawrence D'Anna 
116121b8a8aeSLawrence D'Anna namespace {
116221b8a8aeSLawrence D'Anna class TextPythonFile : public PythonIOFile {
116321b8a8aeSLawrence D'Anna protected:
116421b8a8aeSLawrence D'Anna   int m_descriptor;
116521b8a8aeSLawrence D'Anna 
116621b8a8aeSLawrence D'Anna public:
116721b8a8aeSLawrence D'Anna   TextPythonFile(int fd, const PythonFile &file, bool borrowed)
116821b8a8aeSLawrence D'Anna       : PythonIOFile(file, borrowed),
116921b8a8aeSLawrence D'Anna         m_descriptor(File::DescriptorIsValid(fd) ? fd
117021b8a8aeSLawrence D'Anna                                                  : File::kInvalidDescriptor) {}
117121b8a8aeSLawrence D'Anna 
117221b8a8aeSLawrence D'Anna   int GetDescriptor() const override { return m_descriptor; }
117321b8a8aeSLawrence D'Anna 
117421b8a8aeSLawrence D'Anna   Status Write(const void *buf, size_t &num_bytes) override {
117521b8a8aeSLawrence D'Anna     GIL takeGIL;
117621b8a8aeSLawrence D'Anna     auto pystring =
117721b8a8aeSLawrence D'Anna         PythonString::FromUTF8(llvm::StringRef((const char *)buf, num_bytes));
117821b8a8aeSLawrence D'Anna     if (!pystring)
117921b8a8aeSLawrence D'Anna       return Status(pystring.takeError());
118021b8a8aeSLawrence D'Anna     num_bytes = 0;
118121b8a8aeSLawrence D'Anna     auto bytes_written =
118221b8a8aeSLawrence D'Anna         As<long long>(m_py_obj.CallMethod("write", pystring.get()));
118321b8a8aeSLawrence D'Anna     if (!bytes_written)
118421b8a8aeSLawrence D'Anna       return Status(bytes_written.takeError());
118521b8a8aeSLawrence D'Anna     if (bytes_written.get() < 0)
118621b8a8aeSLawrence D'Anna       return Status(".write() method returned a negative number!");
118721b8a8aeSLawrence D'Anna     static_assert(sizeof(long long) >= sizeof(size_t), "overflow");
118821b8a8aeSLawrence D'Anna     num_bytes = bytes_written.get();
118921b8a8aeSLawrence D'Anna     return Status();
119021b8a8aeSLawrence D'Anna   }
119121b8a8aeSLawrence D'Anna 
119221b8a8aeSLawrence D'Anna   Status Read(void *buf, size_t &num_bytes) override {
119321b8a8aeSLawrence D'Anna     GIL takeGIL;
119421b8a8aeSLawrence D'Anna     size_t num_chars = num_bytes / 6;
119521b8a8aeSLawrence D'Anna     size_t orig_num_bytes = num_bytes;
119621b8a8aeSLawrence D'Anna     num_bytes = 0;
119721b8a8aeSLawrence D'Anna     if (orig_num_bytes < 6) {
119821b8a8aeSLawrence D'Anna       return Status("can't read less than 6 bytes from a utf8 text stream");
119921b8a8aeSLawrence D'Anna     }
120021b8a8aeSLawrence D'Anna     auto pystring = As<PythonString>(
120121b8a8aeSLawrence D'Anna         m_py_obj.CallMethod("read", (unsigned long long)num_chars));
120221b8a8aeSLawrence D'Anna     if (!pystring)
120321b8a8aeSLawrence D'Anna       return Status(pystring.takeError());
120421b8a8aeSLawrence D'Anna     if (pystring.get().IsNone()) {
120521b8a8aeSLawrence D'Anna       // EOF
120621b8a8aeSLawrence D'Anna       return Status();
120721b8a8aeSLawrence D'Anna     }
120821b8a8aeSLawrence D'Anna     auto stringref = pystring.get().AsUTF8();
120921b8a8aeSLawrence D'Anna     if (!stringref)
121021b8a8aeSLawrence D'Anna       return Status(stringref.takeError());
121121b8a8aeSLawrence D'Anna     num_bytes = stringref.get().size();
121221b8a8aeSLawrence D'Anna     memcpy(buf, stringref.get().begin(), num_bytes);
121321b8a8aeSLawrence D'Anna     return Status();
121421b8a8aeSLawrence D'Anna   }
121521b8a8aeSLawrence D'Anna };
121621b8a8aeSLawrence D'Anna } // namespace
121721b8a8aeSLawrence D'Anna 
121821b8a8aeSLawrence D'Anna #endif
121921b8a8aeSLawrence D'Anna 
122021b8a8aeSLawrence D'Anna llvm::Expected<FileSP> PythonFile::ConvertToFile(bool borrowed) {
122121b8a8aeSLawrence D'Anna   if (!IsValid())
122221b8a8aeSLawrence D'Anna     return llvm::createStringError(llvm::inconvertibleErrorCode(),
122321b8a8aeSLawrence D'Anna                                    "invalid PythonFile");
122421b8a8aeSLawrence D'Anna 
122521b8a8aeSLawrence D'Anna   int fd = PyObject_AsFileDescriptor(m_py_obj);
122621b8a8aeSLawrence D'Anna   if (fd < 0) {
122721b8a8aeSLawrence D'Anna     PyErr_Clear();
122821b8a8aeSLawrence D'Anna     return ConvertToFileForcingUseOfScriptingIOMethods(borrowed);
122921b8a8aeSLawrence D'Anna   }
123021b8a8aeSLawrence D'Anna   auto options = GetOptionsForPyObject(*this);
123121b8a8aeSLawrence D'Anna   if (!options)
123221b8a8aeSLawrence D'Anna     return options.takeError();
123321b8a8aeSLawrence D'Anna 
123421b8a8aeSLawrence D'Anna   // LLDB and python will not share I/O buffers.  We should probably
123521b8a8aeSLawrence D'Anna   // flush the python buffers now.
123621b8a8aeSLawrence D'Anna   auto r = CallMethod("flush");
123721b8a8aeSLawrence D'Anna   if (!r)
123821b8a8aeSLawrence D'Anna     return r.takeError();
123921b8a8aeSLawrence D'Anna 
124021b8a8aeSLawrence D'Anna   FileSP file_sp;
124121b8a8aeSLawrence D'Anna   if (borrowed) {
124221b8a8aeSLawrence D'Anna     // In this case we we don't need to retain the python
124321b8a8aeSLawrence D'Anna     // object at all.
124421b8a8aeSLawrence D'Anna     file_sp = std::make_shared<NativeFile>(fd, options.get(), false);
124521b8a8aeSLawrence D'Anna   } else {
124621b8a8aeSLawrence D'Anna     file_sp = std::static_pointer_cast<File>(
124721b8a8aeSLawrence D'Anna         std::make_shared<SimplePythonFile>(*this, borrowed, fd, options.get()));
124821b8a8aeSLawrence D'Anna   }
124921b8a8aeSLawrence D'Anna   if (!file_sp->IsValid())
125021b8a8aeSLawrence D'Anna     return llvm::createStringError(llvm::inconvertibleErrorCode(),
125121b8a8aeSLawrence D'Anna                                    "invalid File");
125221b8a8aeSLawrence D'Anna 
125321b8a8aeSLawrence D'Anna   return file_sp;
125421b8a8aeSLawrence D'Anna }
125521b8a8aeSLawrence D'Anna 
125621b8a8aeSLawrence D'Anna llvm::Expected<FileSP>
125721b8a8aeSLawrence D'Anna PythonFile::ConvertToFileForcingUseOfScriptingIOMethods(bool borrowed) {
125821b8a8aeSLawrence D'Anna 
125921b8a8aeSLawrence D'Anna   assert(!PyErr_Occurred());
126021b8a8aeSLawrence D'Anna 
126121b8a8aeSLawrence D'Anna   if (!IsValid())
126221b8a8aeSLawrence D'Anna     return llvm::createStringError(llvm::inconvertibleErrorCode(),
126321b8a8aeSLawrence D'Anna                                    "invalid PythonFile");
126421b8a8aeSLawrence D'Anna 
126521b8a8aeSLawrence D'Anna #if PY_MAJOR_VERSION < 3
126621b8a8aeSLawrence D'Anna 
126721b8a8aeSLawrence D'Anna   return llvm::createStringError(llvm::inconvertibleErrorCode(),
126821b8a8aeSLawrence D'Anna                                  "not supported on python 2");
126921b8a8aeSLawrence D'Anna 
127021b8a8aeSLawrence D'Anna #else
127121b8a8aeSLawrence D'Anna 
127221b8a8aeSLawrence D'Anna   int fd = PyObject_AsFileDescriptor(m_py_obj);
127321b8a8aeSLawrence D'Anna   if (fd < 0) {
127421b8a8aeSLawrence D'Anna     PyErr_Clear();
127521b8a8aeSLawrence D'Anna     fd = File::kInvalidDescriptor;
127621b8a8aeSLawrence D'Anna   }
127721b8a8aeSLawrence D'Anna 
127821b8a8aeSLawrence D'Anna   auto io_module = PythonModule::Import("io");
127921b8a8aeSLawrence D'Anna   if (!io_module)
128021b8a8aeSLawrence D'Anna     return io_module.takeError();
128121b8a8aeSLawrence D'Anna   auto textIOBase = io_module.get().Get("TextIOBase");
128221b8a8aeSLawrence D'Anna   if (!textIOBase)
128321b8a8aeSLawrence D'Anna     return textIOBase.takeError();
128421b8a8aeSLawrence D'Anna   auto rawIOBase = io_module.get().Get("RawIOBase");
128521b8a8aeSLawrence D'Anna   if (!rawIOBase)
128621b8a8aeSLawrence D'Anna     return rawIOBase.takeError();
128721b8a8aeSLawrence D'Anna   auto bufferedIOBase = io_module.get().Get("BufferedIOBase");
128821b8a8aeSLawrence D'Anna   if (!bufferedIOBase)
128921b8a8aeSLawrence D'Anna     return bufferedIOBase.takeError();
129021b8a8aeSLawrence D'Anna 
129121b8a8aeSLawrence D'Anna   FileSP file_sp;
129221b8a8aeSLawrence D'Anna 
129321b8a8aeSLawrence D'Anna   auto isTextIO = IsInstance(textIOBase.get());
129421b8a8aeSLawrence D'Anna   if (!isTextIO)
129521b8a8aeSLawrence D'Anna     return isTextIO.takeError();
129621b8a8aeSLawrence D'Anna   if (isTextIO.get())
129721b8a8aeSLawrence D'Anna     file_sp = std::static_pointer_cast<File>(
129821b8a8aeSLawrence D'Anna         std::make_shared<TextPythonFile>(fd, *this, borrowed));
129921b8a8aeSLawrence D'Anna 
130021b8a8aeSLawrence D'Anna   auto isRawIO = IsInstance(rawIOBase.get());
130121b8a8aeSLawrence D'Anna   if (!isRawIO)
130221b8a8aeSLawrence D'Anna     return isRawIO.takeError();
130321b8a8aeSLawrence D'Anna   auto isBufferedIO = IsInstance(bufferedIOBase.get());
130421b8a8aeSLawrence D'Anna   if (!isBufferedIO)
130521b8a8aeSLawrence D'Anna     return isBufferedIO.takeError();
130621b8a8aeSLawrence D'Anna 
130721b8a8aeSLawrence D'Anna   if (isRawIO.get() || isBufferedIO.get()) {
130821b8a8aeSLawrence D'Anna     file_sp = std::static_pointer_cast<File>(
130921b8a8aeSLawrence D'Anna         std::make_shared<BinaryPythonFile>(fd, *this, borrowed));
131021b8a8aeSLawrence D'Anna   }
131121b8a8aeSLawrence D'Anna 
131221b8a8aeSLawrence D'Anna   if (!file_sp)
131321b8a8aeSLawrence D'Anna     return llvm::createStringError(llvm::inconvertibleErrorCode(),
131421b8a8aeSLawrence D'Anna                                    "python file is neither text nor binary");
131521b8a8aeSLawrence D'Anna 
131621b8a8aeSLawrence D'Anna   if (!file_sp->IsValid())
131721b8a8aeSLawrence D'Anna     return llvm::createStringError(llvm::inconvertibleErrorCode(),
131821b8a8aeSLawrence D'Anna                                    "invalid File");
131921b8a8aeSLawrence D'Anna 
132021b8a8aeSLawrence D'Anna   return file_sp;
132121b8a8aeSLawrence D'Anna 
132221b8a8aeSLawrence D'Anna #endif
132321b8a8aeSLawrence D'Anna }
132421b8a8aeSLawrence D'Anna 
1325d9b553ecSLawrence D'Anna Expected<PythonFile> PythonFile::FromFile(File &file, const char *mode) {
1326d9b553ecSLawrence D'Anna   if (!file.IsValid())
1327d9b553ecSLawrence D'Anna     return llvm::createStringError(llvm::inconvertibleErrorCode(),
1328d9b553ecSLawrence D'Anna                                    "invalid file");
1329d9b553ecSLawrence D'Anna 
1330d9b553ecSLawrence D'Anna   if (auto *simple = llvm::dyn_cast<SimplePythonFile>(&file))
1331d9b553ecSLawrence D'Anna     return Retain<PythonFile>(simple->GetPythonObject());
1332d9b553ecSLawrence D'Anna #if PY_MAJOR_VERSION >= 3
1333d9b553ecSLawrence D'Anna   if (auto *pythonio = llvm::dyn_cast<PythonIOFile>(&file))
1334d9b553ecSLawrence D'Anna     return Retain<PythonFile>(pythonio->GetPythonObject());
1335d9b553ecSLawrence D'Anna #endif
1336d9b553ecSLawrence D'Anna 
1337d9b553ecSLawrence D'Anna   if (!mode) {
1338d9b553ecSLawrence D'Anna     auto m = file.GetOpenMode();
1339d9b553ecSLawrence D'Anna     if (!m)
1340d9b553ecSLawrence D'Anna       return m.takeError();
1341d9b553ecSLawrence D'Anna     mode = m.get();
1342d9b553ecSLawrence D'Anna   }
1343d9b553ecSLawrence D'Anna 
1344d9b553ecSLawrence D'Anna   PyObject *file_obj;
1345d9b553ecSLawrence D'Anna #if PY_MAJOR_VERSION >= 3
1346d9b553ecSLawrence D'Anna   file_obj = PyFile_FromFd(file.GetDescriptor(), nullptr, mode, -1, nullptr,
1347d9b553ecSLawrence D'Anna                            "ignore", nullptr, 0);
1348d9b553ecSLawrence D'Anna #else
1349d9b553ecSLawrence D'Anna   // Read through the Python source, doesn't seem to modify these strings
1350d9b553ecSLawrence D'Anna   char *cmode = const_cast<char *>(mode);
1351d9b553ecSLawrence D'Anna   // We pass ::flush instead of ::fclose here so we borrow the FILE* --
1352d9b553ecSLawrence D'Anna   // the lldb_private::File still owns it.
1353d9b553ecSLawrence D'Anna   file_obj =
1354d9b553ecSLawrence D'Anna       PyFile_FromFile(file.GetStream(), const_cast<char *>(""), cmode, ::fflush);
1355d9b553ecSLawrence D'Anna #endif
1356d9b553ecSLawrence D'Anna 
1357d9b553ecSLawrence D'Anna   if (!file_obj)
1358d9b553ecSLawrence D'Anna     return exception();
1359d9b553ecSLawrence D'Anna 
1360d9b553ecSLawrence D'Anna   return Take<PythonFile>(file_obj);
1361d9b553ecSLawrence D'Anna }
1362d9b553ecSLawrence D'Anna 
1363d68983e3SPavel Labath #endif
1364